diff --git a/Applications/PluginGenerator/PluginTemplate/documentation/UserManual/Manual.dox b/Applications/PluginGenerator/PluginTemplate/documentation/UserManual/Manual.dox
index 8351db4f16..481dc52e49 100755
--- a/Applications/PluginGenerator/PluginTemplate/documentation/UserManual/Manual.dox
+++ b/Applications/PluginGenerator/PluginTemplate/documentation/UserManual/Manual.dox
@@ -1,18 +1,17 @@
/**
-\page $(plugin-target) $(plugin-name)
+\page $(plugin-target) The $(plugin-name)
\imageMacro{icon.png,"Icon of $(plugin-name)",2.00}
-Available sections:
- - \ref $(plugin-target)Overview
+\tableofcontents
-\section $(plugin-target)Overview
+\section $(plugin-target)Overview Overview
Describe the features of your awesome plugin here
- Increases productivity
- Creates beautiful images
- Generates PhD thesis
- Brings world peace
*/
diff --git a/BlueBerry/BlueBerryConfig.cmake.in b/BlueBerry/BlueBerryConfig.cmake.in
index 5a5d8bbecf..342ae0a783 100644
--- a/BlueBerry/BlueBerryConfig.cmake.in
+++ b/BlueBerry/BlueBerryConfig.cmake.in
@@ -1,91 +1,91 @@
# -------------------------------------------------------------------------
# Package requirements
# -------------------------------------------------------------------------
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "@BLUEBERRY_SOURCE_DIR@/CMake")
set(CTK_DIR "@CTK_DIR@")
find_package(CTK REQUIRED)
set(mbilog_DIR "@mbilog_DIR@")
find_package(mbilog REQUIRED)
find_package(Poco REQUIRED)
set(DOXYGEN_EXECUTABLE "@DOXYGEN_EXECUTABLE@")
set(DOXYGEN_DOT_EXECUTABLE "@DOXYGEN_DOT_EXECUTABLE@")
find_package(Doxygen)
# -------------------------------------------------------------------------
# BlueBerry directory vars
# -------------------------------------------------------------------------
set(BLUEBERRY_PLUGINS_SOURCE_DIR "@BLUEBERRY_PLUGINS_SOURCE_DIR@")
set(BLUEBERRY_PLUGINS_BINARY_DIR "@BLUEBERRY_PLUGINS_BINARY_DIR@")
set(BLUEBERRY_PLUGIN_SOURCE_DIRS "@BLUEBERRY_PLUGINS_SOURCE_DIR@")
set(BLUEBERRY_SOURCE_DIR "@BLUEBERRY_SOURCE_DIR@")
set(BlueBerry_SOURCE_DIR "@BLUEBERRY_SOURCE_DIR@")
set(BLUEBERRY_BINARY_DIR "@BLUEBERRY_BINARY_DIR@")
# -------------------------------------------------------------------------
# BlueBerry CMake file includes
# -------------------------------------------------------------------------
set(BLUEBERRY_PLUGIN_USE_FILE @BB_PLUGIN_USE_FILE@)
if(BLUEBERRY_PLUGIN_USE_FILE)
if(EXISTS ${BLUEBERRY_PLUGIN_USE_FILE})
include(${BLUEBERRY_PLUGIN_USE_FILE})
endif()
endif()
if(NOT BB_PLUGIN_EXPORTS_FILE_INCLUDED AND NOT CMAKE_PROJECT_NAME STREQUAL "MITK")
include("@BB_PLUGIN_EXPORTS_FILE@")
set(BB_PLUGIN_EXPORTS_FILE_INCLUDED 1)
endif()
# -------------------------------------------------------------------------
# BlueBerry CMake variables
# -------------------------------------------------------------------------
set(BLUEBERRY_DEBUG_POSTFIX @BLUEBERRY_DEBUG_POSTFIX@)
set(BLUEBERRY_USE_QT_HELP @BLUEBERRY_USE_QT_HELP@)
-if(BLUEBERRY_USE_QT_HELP AND NOT DOXYGEN_VERSION VERSION_EQUAL "1.8.0")
- message("Setting BLUEBERRY_USE_QT_HELP to OFF because Doxygen version 1.8.0 not found.")
+if(BLUEBERRY_USE_QT_HELP AND DOXYGEN_VERSION VERSION_LESS "1.8.7")
+ message("Setting BLUEBERRY_USE_QT_HELP to OFF because Doxygen version 1.8.7 or newer not found.")
set(BLUEBERRY_USE_QT_HELP OFF)
endif()
set(BLUEBERRY_QTPLUGIN_PATH "@BLUEBERRY_QTPLUGIN_PATH@")
set(QT_HELPGENERATOR_EXECUTABLE "@QT_HELPGENERATOR_EXECUTABLE@")
set(QT_COLLECTIONGENERATOR_EXECUTABLE "@QT_COLLECTIONGENERATOR_EXECUTABLE@")
set(QT_ASSISTANT_EXECUTABLE "@QT_ASSISTANT_EXECUTABLE@")
set(QT_XMLPATTERNS_EXECUTABLE "@QT_XMLPATTERNS_EXECUTABLE@")
set(BLUEBERRY_PLUGIN_TARGETS @my_plugin_targets@)
set(BLUEBERRY_PLUGIN_PROVISIONING_FILE "@BLUEBERRY_PROVISIONING_FILE@")
set(BLUEBERRY_DOXYGEN_TAGFILE_NAME @BLUEBERRY_DOXYGEN_TAGFILE_NAME@)
# -------------------------------------------------------------------------
# BlueBerry CMake macros
# -------------------------------------------------------------------------
include(MacroParseArguments)
include(MacroConvertSchema)
include(MacroOrganizeSources)
include(MacroCreateCTKPlugin)
include(MacroCreateQtHelp)
include(MacroInstallCTKPlugin)
include(FunctionInstallThirdPartyCTKPlugins)
include(FunctionCreateProvisioningFile)
include(FunctionCreateBlueBerryApplication)
diff --git a/BlueBerry/Bundles/org.blueberry.ui.qt/src/internal/berryQtStylePreferencePage.cpp b/BlueBerry/Bundles/org.blueberry.ui.qt/src/internal/berryQtStylePreferencePage.cpp
index e6d42122c4..a82637097f 100644
--- a/BlueBerry/Bundles/org.blueberry.ui.qt/src/internal/berryQtStylePreferencePage.cpp
+++ b/BlueBerry/Bundles/org.blueberry.ui.qt/src/internal/berryQtStylePreferencePage.cpp
@@ -1,246 +1,247 @@
/*===================================================================
BlueBerry Platform
Copyright (c) German Cancer Research Center,
Division of Medical and Biological Informatics.
All rights reserved.
This software is distributed WITHOUT ANY WARRANTY; without
even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE.
See LICENSE.txt or http://www.mitk.org for details.
===================================================================*/
#include "berryQtStylePreferencePage.h"
#include
#include
#include
#include
namespace berry
{
QtStylePreferencePage::QtStylePreferencePage()
{
}
QtStylePreferencePage::QtStylePreferencePage(const QtStylePreferencePage& other)
{
Q_UNUSED(other)
}
void QtStylePreferencePage::Init(IWorkbench::Pointer )
{
}
void QtStylePreferencePage::CreateQtControl(QWidget* parent)
{
mainWidget = new QWidget(parent);
controls.setupUi(mainWidget);
berry::IPreferencesService::Pointer prefService
= berry::Platform::GetServiceRegistry()
.GetServiceById(berry::IPreferencesService::ID);
styleManager = berry::Platform::GetServiceRegistry()
.GetServiceById(berry::IQtStyleManager::ID);
m_StylePref = prefService->GetSystemPreferences()->Node(berry::QtPreferences::QT_STYLES_NODE);
Update();
connect(controls.m_StylesCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(StyleChanged(int)));
connect(controls.m_IconThemeComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(IconThemeChanged(int)));
connect(controls.m_PathList, SIGNAL(itemSelectionChanged()), this, SLOT(UpdatePathListButtons()));
connect(controls.m_AddButton, SIGNAL(clicked(bool)), this, SLOT(AddPathClicked(bool)));
connect(controls.m_EditButton, SIGNAL(clicked(bool)), this, SLOT(EditPathClicked(bool)));
connect(controls.m_RemoveButton, SIGNAL(clicked(bool)), this, SLOT(RemovePathClicked(bool)));
}
void QtStylePreferencePage::FillStyleCombo(const berry::IQtStyleManager::Style& currentStyle)
{
controls.m_StylesCombo->clear();
styles.clear();
styleManager->GetStyles(styles);
qSort(styles);
for (int i = 0; i < styles.size(); ++i)
{
controls.m_StylesCombo->addItem(styles.at(i).name, QVariant(styles.at(i).fileName));
}
controls.m_StylesCombo->setCurrentIndex(styles.indexOf(currentStyle));
}
-void QtStylePreferencePage::FillIconThemeComboBox()
+void QtStylePreferencePage::FillIconThemeComboBox(const QString currentIconTheme)
{
controls.m_IconThemeComboBox->clear();
berry::IQtStyleManager::IconThemeList iconThemes;
styleManager->GetIconThemes(iconThemes);
qSort(iconThemes);
for (int i = 0; i < iconThemes.size(); ++i)
{
controls.m_IconThemeComboBox->addItem(iconThemes.at(i).name);
}
- QString currentTheme = QIcon::themeName();
+ QString currentTheme = currentIconTheme;
+
if(currentTheme == QString(""))
{
currentTheme = QString("<>");
}
controls.m_IconThemeComboBox->setCurrentIndex(iconThemes.indexOf( currentTheme ));
}
void QtStylePreferencePage::AddPath(const QString& path, bool updateCombo)
{
if (!controls.m_PathList->findItems(path, Qt::MatchCaseSensitive).isEmpty()) return;
new QListWidgetItem(path, controls.m_PathList);
styleManager->AddStyles(path);
if (updateCombo)
FillStyleCombo(oldStyle);
}
void QtStylePreferencePage::StyleChanged(int /*index*/)
{
QString fileName = controls.m_StylesCombo->itemData(controls.m_StylesCombo->currentIndex()).toString();
styleManager->SetStyle(fileName);
}
void QtStylePreferencePage::IconThemeChanged(int /*index*/)
{
QString themeName = controls.m_IconThemeComboBox->currentText();
styleManager->SetIconTheme(themeName);
}
void QtStylePreferencePage::AddPathClicked(bool /*checked*/)
{
QListWidgetItem* item = controls.m_PathList->currentItem();
QString initialDir;
if (item) initialDir = item->text();
QString dir = QFileDialog::getExistingDirectory(mainWidget, "", initialDir);
if (!dir.isEmpty()) this->AddPath(dir, true);
}
void QtStylePreferencePage::RemovePathClicked(bool /*checked*/)
{
QList selection = controls.m_PathList->selectedItems();
QListIterator it(selection);
while (it.hasNext())
{
QListWidgetItem* item = it.next();
QString dir = item->text();
controls.m_PathList->takeItem(controls.m_PathList->row(item));
delete item;
styleManager->RemoveStyles(dir);
}
if (!styleManager->Contains(oldStyle.fileName))
{
oldStyle = styleManager->GetDefaultStyle();
}
FillStyleCombo(oldStyle);
}
void QtStylePreferencePage::EditPathClicked(bool checked)
{
QListWidgetItem* item = controls.m_PathList->currentItem();
QString initialDir = item->text();
QString dir = QFileDialog::getExistingDirectory(mainWidget, "", initialDir);
if (!dir.isEmpty())
{
this->RemovePathClicked(checked);
this->AddPath(dir, true);
}
}
void QtStylePreferencePage::UpdatePathListButtons()
{
int s = controls.m_PathList->selectedItems().size();
if (s == 0)
{
controls.m_EditButton->setEnabled(false);
controls.m_RemoveButton->setEnabled(false);
}
else if (s == 1)
{
controls.m_EditButton->setEnabled(true);
controls.m_RemoveButton->setEnabled(true);
}
else
{
controls.m_EditButton->setEnabled(false);
controls.m_RemoveButton->setEnabled(true);
}
}
QWidget* QtStylePreferencePage::GetQtControl() const
{
return mainWidget;
}
bool QtStylePreferencePage::PerformOk()
{
m_StylePref->Put(berry::QtPreferences::QT_STYLE_NAME,
controls.m_StylesCombo->itemData(controls.m_StylesCombo->currentIndex()).toString().toStdString());
std::string paths;
for (int i = 0; i < controls.m_PathList->count(); ++i)
{
QString path = controls.m_PathList->item(i)->text() + ";";
paths += path.toStdString();
}
QString currentTheme = QIcon::themeName();
if(currentTheme == QString(""))
{
currentTheme = QString("<>");
}
m_StylePref->Put(berry::QtPreferences::QT_STYLE_SEARCHPATHS, paths);
m_StylePref->Put(berry::QtPreferences::QT_ICON_THEME, currentTheme.toStdString());
return true;
}
void QtStylePreferencePage::PerformCancel()
{
Update();
}
void QtStylePreferencePage::Update()
{
styleManager->RemoveStyles();
QString paths = QString::fromStdString(m_StylePref->Get(berry::QtPreferences::QT_STYLE_SEARCHPATHS, ""));
QStringList pathList = paths.split(";", QString::SkipEmptyParts);
QStringListIterator it(pathList);
while (it.hasNext())
{
AddPath(it.next(), false);
}
QString iconTheme = QString::fromStdString(m_StylePref->Get(berry::QtPreferences::QT_ICON_THEME, "<>"));
styleManager->SetIconTheme( iconTheme );
std::string name = m_StylePref->Get(berry::QtPreferences::QT_STYLE_NAME, "");
styleManager->SetStyle(QString::fromStdString(name));
oldStyle = styleManager->GetStyle();
FillStyleCombo(oldStyle);
- FillIconThemeComboBox();
+ FillIconThemeComboBox( iconTheme );
}
}
diff --git a/BlueBerry/Bundles/org.blueberry.ui.qt/src/internal/berryQtStylePreferencePage.h b/BlueBerry/Bundles/org.blueberry.ui.qt/src/internal/berryQtStylePreferencePage.h
index 124458db09..8568d6f300 100644
--- a/BlueBerry/Bundles/org.blueberry.ui.qt/src/internal/berryQtStylePreferencePage.h
+++ b/BlueBerry/Bundles/org.blueberry.ui.qt/src/internal/berryQtStylePreferencePage.h
@@ -1,83 +1,83 @@
/*===================================================================
BlueBerry Platform
Copyright (c) German Cancer Research Center,
Division of Medical and Biological Informatics.
All rights reserved.
This software is distributed WITHOUT ANY WARRANTY; without
even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE.
See LICENSE.txt or http://www.mitk.org for details.
===================================================================*/
#ifndef BERRYQTSTYLEPREFERENCEPAGE_H_
#define BERRYQTSTYLEPREFERENCEPAGE_H_
#include
#include
#include
#include
#include
namespace berry {
class QtStylePreferencePage : public QObject, public IQtPreferencePage
{
Q_OBJECT
Q_INTERFACES(berry::IPreferencePage)
public:
QtStylePreferencePage();
QtStylePreferencePage(const QtStylePreferencePage& other);
void Init(IWorkbench::Pointer workbench);
void CreateQtControl(QWidget* parent);
QWidget* GetQtControl() const;
bool PerformOk();
void PerformCancel();
void Update();
protected:
void AddPath(const QString& path, bool updateCombo);
void FillStyleCombo(const berry::IQtStyleManager::Style& currentStyle);
- void FillIconThemeComboBox();
+ void FillIconThemeComboBox(const QString currentIconTheme);
protected slots:
void StyleChanged(int /*index*/);
void IconThemeChanged(int /*index*/);
void AddPathClicked(bool /*checked*/);
void RemovePathClicked(bool /*checked*/);
void EditPathClicked(bool checked);
void UpdatePathListButtons();
private:
berry::IQtStyleManager::Pointer styleManager;
Ui::QtStylePreferencePageUI controls;
berry::IPreferences::Pointer m_StylePref;
berry::IQtStyleManager::Style oldStyle;
berry::IQtStyleManager::StyleList styles;
QWidget* mainWidget;
};
}
#endif /* BERRYQTSTYLEPREFERENCEPAGE_H_ */
diff --git a/BlueBerry/CMakeLists.txt b/BlueBerry/CMakeLists.txt
index 75db3b02a0..3b77eba726 100644
--- a/BlueBerry/CMakeLists.txt
+++ b/BlueBerry/CMakeLists.txt
@@ -1,285 +1,285 @@
project(BlueBerry)
if (${CMAKE_SOURCE_DIR} EQUAL ${PROJECT_SOURCE_DIR})
cmake_minimum_required(VERSION 2.8.9)
endif()
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/CMake/")
include(MacroParseArguments)
include(MacroConvertSchema)
include(MacroOrganizeSources)
include(MacroCreateCTKPlugin)
include(MacroCreateQtHelp)
include(MacroInstallCTKPlugin)
include(FunctionCreateProvisioningFile)
if(MSVC)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DNOMINMAX /wd4250 /wd4275 /wd4251 /wd4503")
endif()
if(NOT CMAKE_RUNTIME_OUTPUT_DIRECTORY)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/bin)
endif()
find_package(mbilog REQUIRED)
include_directories(${mbilog_INCLUDE_DIRS})
if(MITK_USE_Qt4)
find_package(Qt4 4.7 REQUIRED)
else()
find_package(Qt5Concurrent ${MITK_QT5_MINIMUM_VERSION} REQUIRED)
find_package(Qt5Help ${MITK_QT5_MINIMUM_VERSION} REQUIRED)
find_package(Qt5Sql ${MITK_QT5_MINIMUM_VERSION} REQUIRED)
find_package(Qt5WebKitWidgets ${MITK_QT5_MINIMUM_VERSION} REQUIRED)
find_package(Qt5Widgets ${MITK_QT5_MINIMUM_VERSION} REQUIRED)
find_package(Qt5Xml ${MITK_QT5_MINIMUM_VERSION} REQUIRED)
endif()
if(QT_QMAKE_CHANGED)
set(QT_HELPGENERATOR_EXECUTABLE NOTFOUND)
set(QT_COLLECTIONGENERATOR_EXECUTABLE NOTFOUND)
set(QT_ASSISTANT_EXECUTABLE NOTFOUND)
set(QT_XMLPATTERNS_EXECUTABLE NOTFOUND)
endif()
find_program(QT_HELPGENERATOR_EXECUTABLE
NAMES qhelpgenerator qhelpgenerator-qt4 qhelpgenerator4
PATHS ${QT_BINARY_DIR}
NO_DEFAULT_PATH
)
find_program(QT_COLLECTIONGENERATOR_EXECUTABLE
NAMES qcollectiongenerator qcollectiongenerator-qt4 qcollectiongenerator4
PATHS ${QT_BINARY_DIR}
NO_DEFAULT_PATH
)
find_program(QT_ASSISTANT_EXECUTABLE
NAMES assistant-qt4 assistant4 assistant
PATHS ${QT_BINARY_DIR}
NO_DEFAULT_PATH
)
find_program(QT_XMLPATTERNS_EXECUTABLE
NAMES xmlpatterns
PATHS ${QT_BINARY_DIR}
NO_DEFAULT_PATH
)
find_package(Doxygen)
option(BLUEBERRY_USE_QT_HELP "Enable support for integrating bundle documentation into Qt Help" ${DOXYGEN_FOUND})
mark_as_advanced(BLUEBERRY_USE_QT_HELP
QT_HELPGENERATOR_EXECUTABLE
QT_COLLECTIONGENERATOR_EXECUTABLE
QT_ASSISTANT_EXECUTABLE
QT_XMLPATTERNS_EXECUTABLE)
if(BLUEBERRY_USE_QT_HELP)
set(_force_blueberry_use_qt_help_to_off 0)
if(NOT DOXYGEN_FOUND)
message("> Forcing BLUEBERRY_USE_QT_HELP to OFF because Doxygen was not found.")
set(_force_blueberry_use_qt_help_to_off 1)
endif()
- if(DOXYGEN_FOUND AND NOT DOXYGEN_VERSION VERSION_EQUAL 1.8.0)
- message("> Forcing BLUEBERRY_USE_QT_HELP to OFF because Doxygen version 1.8.0 not found.")
+ if(DOXYGEN_FOUND AND DOXYGEN_VERSION VERSION_LESS 1.8.7)
+ message("> Forcing BLUEBERRY_USE_QT_HELP to OFF because Doxygen version 1.8.7 or newer not found.")
set(_force_blueberry_use_qt_help_to_off 1)
endif()
if(NOT QT_HELPGENERATOR_EXECUTABLE)
message("> Forcing BLUEBERRY_USE_QT_HELP to OFF because QT_HELPGENERATOR_EXECUTABLE is empty.")
set(_force_blueberry_use_qt_help_to_off 1)
endif()
if(NOT QT_XMLPATTERNS_EXECUTABLE)
message("You have enabled Qt Help support, but QT_XMLPATTERNS_EXECUTABLE is empty")
set(_force_blueberry_use_qt_help_to_off 1)
endif()
if(_force_blueberry_use_qt_help_to_off)
set(BLUEBERRY_USE_QT_HELP OFF CACHE BOOL "Enable support for integrating bundle documentation into Qt Help" FORCE)
endif()
endif(BLUEBERRY_USE_QT_HELP)
if(MITK_USE_Qt4)
include(${QT_USE_FILE})
endif()
# ========= CTK specific CMake stuff ============
cmake_policy(SET CMP0012 NEW)
find_package(CTK REQUIRED)
# Extract all library names starting with org_blueberry_
macro(GetMyTargetLibraries all_target_libraries varname)
set(re_ctkplugin "^org_blueberry_[a-zA-Z0-9_]+$")
set(_tmp_list)
list(APPEND _tmp_list ${all_target_libraries})
ctkMacroListFilter(_tmp_list re_ctkplugin OUTPUT_VARIABLE ${varname})
endmacro()
# ================================================
option(BLUEBERRY_BUILD_ALL_PLUGINS "Build all BlueBerry plugins (overriding selection)" OFF)
mark_as_advanced(BLUEBERRY_BUILD_ALL_PLUGINS)
if(BLUEBERRY_BUILD_ALL_PLUGINS)
set(BLUEBERRY_BUILD_ALL_PLUGINS_OPTION "FORCE_BUILD_ALL")
endif()
option(BLUEBERRY_STATIC "Build all plugins as static libraries" OFF)
mark_as_advanced(BLUEBERRY_STATIC)
option(BLUEBERRY_DEBUG_SMARTPOINTER "Enable code for debugging smart pointers" OFF)
mark_as_advanced(BLUEBERRY_DEBUG_SMARTPOINTER)
find_package(Poco REQUIRED)
find_package(Ant)
find_package(Eclipse)
set(BLUEBERRY_SOURCE_DIR ${BlueBerry_SOURCE_DIR})
set(BLUEBERRY_BINARY_DIR ${BlueBerry_BINARY_DIR})
set(BLUEBERRY_PLUGINS_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/Bundles)
set(BLUEBERRY_PLUGINS_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}/Bundles)
set(OSGI_APP solstice)
set(OSGI_UI_APP solstice_ui)
if(Eclipse_DIR)
set(BLUEBERRY_DOC_TOOLS_DIR "${Eclipse_DIR}" CACHE PATH "Directory containing additional tools needed for generating the documentation")
else()
set(BLUEBERRY_DOC_TOOLS_DIR "" CACHE PATH "Directory containing additional tools needed for generating the documentation")
endif()
set(BLUEBERRY_DEBUG_POSTFIX d)
# Testing options
if(DEFINED BLUEBERRY_BUILD_TESTING)
option(BLUEBERRY_BUILD_TESTING "Build the BlueBerry tests." ${BLUEBERRY_BUILD_TESTING})
else()
option(BLUEBERRY_BUILD_TESTING "Build the BlueBerry tests." ${BUILD_TESTING})
endif()
if(WIN32)
set(_gui_testing_default "ON")
else()
set(_gui_testing_default "OFF")
endif()
option(BLUEBERRY_ENABLE_GUI_TESTING "Enable the BlueBerry GUI tests" ${_gui_testing_default})
mark_as_advanced(BLUEBERRY_ENABLE_GUI_TESTING)
if(BLUEBERRY_BUILD_TESTING)
enable_testing()
endif()
# Add CTK plugins
set(_ctk_plugins
Bundles/org.blueberry.osgi:ON
Bundles/org.blueberry.compat:OFF
Bundles/org.blueberry.core.runtime:OFF
Bundles/org.blueberry.core.expressions:OFF
Bundles/org.blueberry.solstice.common:OFF
Bundles/org.blueberry.core.commands:OFF
Bundles/org.blueberry.core.jobs:OFF
Bundles/org.blueberry.ui:OFF
Bundles/org.blueberry.ui.qt:OFF
Bundles/org.blueberry.ui.qt.help:OFF
Bundles/org.blueberry.ui.qt.log:ON
Bundles/org.blueberry.ui.qt.objectinspector:OFF
)
set(_ctk_test_plugins )
set(_ctk_plugins_include_dirs
${Poco_INCLUDE_DIRS}
)
include_directories(${_ctk_plugins_include_dirs})
if(BLUEBERRY_BUILD_TESTING)
find_package(CppUnit REQUIRED)
include(berryTestingHelpers)
set(BLUEBERRY_TEST_APP "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${OSGI_APP}")
get_target_property(_is_macosx_bundle ${OSGI_APP} MACOSX_BUNDLE)
if(APPLE AND _is_macosx_bundle)
set(BLUEBERRY_TEST_APP "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${OSGI_APP}.app/Contents/MacOS/${OSGI_APP}")
endif()
set(_ctk_testinfrastructure_plugins
Bundles/org.blueberry.test:ON
Bundles/org.blueberry.uitest:ON
)
set(_ctk_test_plugins
# Testing/org.blueberry.core.runtime.tests:ON
# Testing/org.blueberry.osgi.tests:ON
)
if(BLUEBERRY_ENABLE_GUI_TESTING)
# list(APPEND _ctk_test_plugins Testing/org.blueberry.ui.tests:ON)
set(BLUEBERRY_UI_TEST_APP "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${OSGI_UI_APP}")
get_target_property(_is_macosx_bundle ${OSGI_UI_APP} MACOSX_BUNDLE)
if(APPLE AND _is_macosx_bundle)
set(BLUEBERRY_UI_TEST_APP "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${OSGI_UI_APP}.app/Contents/MacOS/${OSGI_UI_APP}")
endif()
endif()
endif()
set(BLUEBERRY_TESTING_PROVISIONING_FILE "${BlueBerry_BINARY_DIR}/BlueBerryTesting.provisioning")
add_custom_target(BlueBerry)
ctkMacroSetupPlugins(${_ctk_plugins} ${_ctk_testinfrastructure_plugins} ${_ctk_test_plugins}
BUILD_OPTION_PREFIX BLUEBERRY_BUILD_
BUILD_ALL ${BLUEBERRY_BUILD_ALL_PLUGINS}
COMPACT_OPTIONS)
set(BLUEBERRY_PROVISIONING_FILE "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/BlueBerry.provisioning")
FunctionCreateProvisioningFile(
FILE ${BLUEBERRY_PROVISIONING_FILE}
PLUGINS ${_ctk_plugins}
)
FunctionCreateProvisioningFile(
FILE ${BLUEBERRY_TESTING_PROVISIONING_FILE}
INCLUDE ${BLUEBERRY_PROVISIONING_FILE}
PLUGINS ${_ctk_testinfrastructure_plugins} ${_ctk_test_plugins}
)
if(${CMAKE_PROJECT_NAME}_PLUGIN_LIBRARIES)
add_dependencies(BlueBerry ${${CMAKE_PROJECT_NAME}_PLUGIN_LIBRARIES})
endif()
set_property(TARGET ${${CMAKE_PROJECT_NAME}_PLUGIN_LIBRARIES} PROPERTY LABELS BlueBerry)
set(BB_PLUGIN_USE_FILE "${BlueBerry_BINARY_DIR}/BlueBerryPluginUseFile.cmake")
if(${PROJECT_NAME}_PLUGIN_LIBRARIES)
ctkFunctionGeneratePluginUseFile(${BB_PLUGIN_USE_FILE})
else()
file(REMOVE ${BB_PLUGIN_USE_FILE})
set(BB_PLUGIN_USE_FILE )
endif()
# CTK Plugin Exports
set(BB_PLUGIN_EXPORTS_FILE "${CMAKE_CURRENT_BINARY_DIR}/BlueBerryPluginExports.cmake")
GetMyTargetLibraries("${${PROJECT_NAME}_PLUGIN_LIBRARIES}" my_plugin_targets)
set(additional_export_targets mbilog)
export(TARGETS ${my_plugin_targets} ${additional_export_targets}
FILE ${BB_PLUGIN_EXPORTS_FILE})
add_subdirectory(Documentation)
set(BLUEBERRY_QTPLUGIN_PATH )
if(CTK_QTDESIGNERPLUGINS_DIR AND EXISTS ${CTK_QTDESIGNERPLUGINS_DIR})
set(BLUEBERRY_QTPLUGIN_PATH "${CTK_QTDESIGNERPLUGINS_DIR}")
endif()
configure_file(BlueBerryConfig.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/BlueBerryConfig.cmake @ONLY)
diff --git a/CMake/MITKDashboardDriverScript.cmake b/CMake/MITKDashboardDriverScript.cmake
index 2c75718c26..4c36060d43 100644
--- a/CMake/MITKDashboardDriverScript.cmake
+++ b/CMake/MITKDashboardDriverScript.cmake
@@ -1,484 +1,485 @@
#
# Included from a dashboard script, this cmake file will drive the configure and build
# steps of MITK
#
#-----------------------------------------------------------------------------
# The following variable are expected to be define in the top-level script:
set(expected_variables
CTEST_NOTES_FILES
CTEST_SITE
CTEST_DASHBOARD_ROOT
CTEST_CMAKE_COMMAND
CTEST_CMAKE_GENERATOR
WITH_MEMCHECK
WITH_COVERAGE
WITH_DOCUMENTATION
CTEST_BUILD_CONFIGURATION
CTEST_TEST_TIMEOUT
CTEST_BUILD_FLAGS
TEST_TO_EXCLUDE_REGEX
CTEST_SOURCE_DIRECTORY
CTEST_BINARY_DIRECTORY
CTEST_BUILD_NAME
SCRIPT_MODE
CTEST_COVERAGE_COMMAND
CTEST_MEMORYCHECK_COMMAND
CTEST_GIT_COMMAND
PROJECT_BUILD_DIR
SUPERBUILD_TARGETS
)
foreach(var ${expected_variables})
if(NOT DEFINED ${var})
message(FATAL_ERROR "Variable ${var} should be defined in top-level script !")
endif()
endforeach()
# Check if "mbits" is reachable
file(DOWNLOAD "http://mbits" "${CTEST_SCRIPT_DIRECTORY}/mbits.html" TIMEOUT 2 STATUS _status)
list(GET _status 0 _status_code)
if(_status_code EQUAL 6) # couldn't resovle host name
set(MBITS_AVAILABLE 0)
else()
set(MBITS_AVAILABLE 1)
endif()
#
# Site specific options
#
if(NOT CDASH_ADMIN_URL_PREFIX AND MBITS_AVAILABLE)
set(CDASH_ADMIN_URL_PREFIX "http://mbits")
endif()
if(NOT MITK_THIRDPARTY_DOWNLOAD_PREFIX_URL AND MBITS_AVAILABLE)
set(MITK_THIRDPARTY_DOWNLOAD_PREFIX_URL "http://mbits/dl-cache")
endif()
if(NOT DEFINED GIT_BRANCH OR GIT_BRANCH STREQUAL "")
set(GIT_BRANCH "")
else()
set(GIT_BRANCH "-b ${GIT_BRANCH}")
endif()
# Should binary directory be cleaned?
set(empty_binary_directory FALSE)
# Attempt to build and test also if 'ctest_update' returned an error
set(initial_force_build FALSE)
# Set model options
set(model "")
if(SCRIPT_MODE STREQUAL "experimental")
set(empty_binary_directory FALSE)
set(initial_force_build TRUE)
set(model Experimental)
elseif(SCRIPT_MODE STREQUAL "continuous")
set(empty_binary_directory FALSE)
set(initial_force_build FALSE)
set(model Continuous)
elseif(SCRIPT_MODE STREQUAL "nightly")
set(empty_binary_directory TRUE)
set(initial_force_build TRUE)
set(model Nightly)
else()
message(FATAL_ERROR "Unknown script mode: '${SCRIPT_MODE}'. Script mode should be either 'experimental', 'continuous' or 'nightly'")
endif()
#message("script_mode:${SCRIPT_MODE}")
#message("model:${model}")
#message("empty_binary_directory:${empty_binary_directory}")
#message("force_build:${initial_force_build}")
set(CTEST_CONFIGURATION_TYPE ${CTEST_BUILD_CONFIGURATION})
if(empty_binary_directory)
message("Directory ${CTEST_BINARY_DIRECTORY} cleaned !")
ctest_empty_binary_directory(${CTEST_BINARY_DIRECTORY})
endif()
if(NOT DEFINED CTEST_CHECKOUT_DIR)
set(CTEST_CHECKOUT_DIR ${CTEST_SOURCE_DIRECTORY})
endif()
if(NOT EXISTS "${CTEST_CHECKOUT_DIR}")
set(CTEST_CHECKOUT_COMMAND "\"${CTEST_GIT_COMMAND}\" clone ${GIT_BRANCH} ${GIT_REPOSITORY} \"${CTEST_CHECKOUT_DIR}\"")
endif()
set(CTEST_UPDATE_TYPE "git")
set(CTEST_UPDATE_COMMAND "${CTEST_GIT_COMMAND}")
#----------------------------------------------------------------------
# Utility macros
#----------------------------------------------------------------------
function(func_build_target target build_dir)
set(CTEST_BUILD_TARGET ${target})
ctest_build(BUILD "${build_dir}" APPEND
RETURN_VALUE res
NUMBER_ERRORS num_errors
NUMBER_WARNINGS num_warnings)
ctest_submit(PARTS Build RETRY_DELAY 3 RETRY_COUNT 3)
if(num_errors)
math(EXPR build_errors "${build_errors} + ${num_errors}")
set(build_errors ${build_errors} PARENT_SCOPE)
endif()
if(num_warnings)
math(EXPR build_warnings "${build_warnings} + ${num_warnings}")
set(build_warnings ${build_warnings} PARENT_SCOPE)
endif()
endfunction()
function(func_test label build_dir)
if(NOT TESTING_PARALLEL_LEVEL)
set(TESTING_PARALLEL_LEVEL 8)
endif()
if(label MATCHES "Unlabeled")
set(_include_label EXCLUDE_LABEL .*)
else()
set(_include_label INCLUDE_LABEL ${label})
endif()
ctest_test(BUILD "${build_dir}"
${_include_label}
PARALLEL_LEVEL ${TESTING_PARALLEL_LEVEL}
EXCLUDE ${TEST_TO_EXCLUDE_REGEX}
RETURN_VALUE res
)
ctest_submit(PARTS Test RETRY_DELAY 3 RETRY_COUNT 3)
if(res)
math(EXPR test_errors "${test_errors} + 1")
set(test_errors ${test_errors} PARENT_SCOPE)
endif()
if(ARG3)
set(WITH_COVERAGE ${ARG3})
endif()
if(ARG4)
set(WITH_MEMCHECK ${ARG4})
endif()
if(WITH_COVERAGE AND CTEST_COVERAGE_COMMAND)
message("----------- [ Coverage ${label} ] -----------")
ctest_coverage(BUILD "${build_dir}" LABELS ${label})
ctest_submit(PARTS Coverage RETRY_DELAY 3 RETRY_COUNT 3)
endif()
if(WITH_MEMCHECK AND CTEST_MEMORYCHECK_COMMAND)
if(NOT CTEST_MEMORYCHECK_SUPPRESSIONS_FILE)
if(EXISTS "${CTEST_SOURCE_DIRECTORY}/CMake/valgrind.supp")
set(CTEST_MEMORYCHECK_SUPPRESSIONS_FILE "${CTEST_SOURCE_DIRECTORY}/CMake/valgrind.supp")
endif()
endif()
if(NOT CTEST_MEMORYCHECK_COMMAND_OPTIONS)
set(CTEST_MEMORYCHECK_COMMAND_OPTIONS "-q --tool=memcheck --leak-check=yes --show-reachable=no --show-possibly-lost=no --workaround-gcc296-bugs=yes --num-callers=50")
endif()
ctest_memcheck(BUILD "${build_dir}" INCLUDE_LABEL ${label})
ctest_submit(PARTS MemCheck RETRY_DELAY 3 RETRY_COUNT 3)
endif()
endfunction()
#---------------------------------------------------------------------
# run_ctest macro
#---------------------------------------------------------------------
macro(run_ctest)
set(build_warnings 0)
set(build_errors 0)
set(test_errors 0)
ctest_start(${model})
ctest_update(SOURCE "${CTEST_CHECKOUT_DIR}" RETURN_VALUE res)
if(res LESS 0)
# update error
math(EXPR build_errors "${build_errors} + 1")
endif()
set(force_build ${initial_force_build})
# Check if a forced run was requested
set(cdash_remove_rerun_url )
if(CDASH_ADMIN_URL_PREFIX)
set(cdash_rerun_url "${CDASH_ADMIN_URL_PREFIX}/rerun/${CTEST_BUILD_NAME}")
set(cdash_remove_rerun_url "${CDASH_ADMIN_URL_PREFIX}/rerun/rerun.php?name=${CTEST_BUILD_NAME}&remove=1")
file(DOWNLOAD
"${cdash_rerun_url}"
"${CTEST_BINARY_DIRECTORY}/tmp.txt"
STATUS status
)
list(GET status 0 error_code)
file(READ "${CTEST_BINARY_DIRECTORY}/tmp.txt" rerun_content LIMIT 1)
if(NOT error_code AND NOT rerun_content)
set(force_build 1)
endif()
endif()
if(COMMAND MITK_OVERRIDE_FORCE_BUILD)
MITK_OVERRIDE_FORCE_BUILD(force_build)
endif()
# force a build if this is the first run and the build dir is empty
if(NOT EXISTS "${CTEST_BINARY_DIRECTORY}/CMakeCache.txt")
message("First time build - Initialize CMakeCache.txt")
set(res 1)
# Write initial cache.
if(NOT DEFINED BUILD_TESTING)
set(BUILD_TESTING ON)
endif()
# Write initial cache.
file(WRITE "${CTEST_BINARY_DIRECTORY}/CMakeCache.txt" "
CTEST_USE_LAUNCHERS:BOOL=${CTEST_USE_LAUNCHERS}
CTEST_PROJECT_ADDITIONAL_TARGETS:INTERNAL=${CTEST_PROJECT_ADDITIONAL_TARGETS}
BUILD_TESTING:BOOL=${BUILD_TESTING}
MITK_CTEST_SCRIPT_MODE:STRING=${SCRIPT_MODE}
CMAKE_BUILD_TYPE:STRING=${CTEST_BUILD_CONFIGURATION}
WITH_COVERAGE:BOOL=${WITH_COVERAGE}
MITK_THIRDPARTY_DOWNLOAD_PREFIX_URL:STRING=${MITK_THIRDPARTY_DOWNLOAD_PREFIX_URL}
${INITIAL_CMAKECACHE_OPTIONS}
")
endif()
if(res GREATER 0 OR force_build)
# Clear the forced rerun request
if(CDASH_ADMIN_URL_PREFIX AND cdash_remove_rerun_url)
file(DOWNLOAD "${cdash_remove_rerun_url}" "${CTEST_BINARY_DIRECTORY}/tmp.txt")
file(REMOVE "${CTEST_BINARY_DIRECTORY}/tmp.txt")
endif()
if(CTEST_PROJECT_NAME_SUPERBUILD)
set(ctest_project_name_orig ${CTEST_PROJECT_NAME})
set(CTEST_PROJECT_NAME ${CTEST_PROJECT_NAME_SUPERBUILD})
endif()
message("----------- [ Configure SuperBuild ] -----------")
set_property(GLOBAL PROPERTY SubProject SuperBuild)
set_property(GLOBAL PROPERTY Label SuperBuild)
ctest_configure(BUILD "${CTEST_BINARY_DIRECTORY}" RETURN_VALUE res OPTIONS "${SUPERBUILD_CONFIG_OPTIONS}")
if(res)
math(EXPR build_errors "${build_errors} + 1")
endif()
# Project.xml is generated during the superbuild configure step
ctest_submit(FILES "${CTEST_BINARY_DIRECTORY}/Project.xml" RETRY_DELAY 3 RETRY_COUNT 3)
ctest_read_custom_files("${CTEST_BINARY_DIRECTORY}")
ctest_submit(PARTS Configure RETRY_DELAY 3 RETRY_COUNT 3)
# submit the update results *after* the submitting the Configure info,
# otherwise CDash is somehow confused and cannot add the update info
# to the superbuild project
ctest_submit(PARTS Update RETRY_DELAY 3 RETRY_COUNT 3)
# To get CTEST_PROJECT_SUBPROJECTS and CTEST_PROJECT_EXTERNALS definition
include("${CTEST_BINARY_DIRECTORY}/CTestConfigSubProject.cmake")
# Build top level (either all or the supplied targets at
# superbuild level
if(SUPERBUILD_TARGETS AND NOT build_errors)
foreach(superbuild_target ${SUPERBUILD_TARGETS})
message("----------- [ Build ${superbuild_target} - SuperBuild ] -----------")
func_build_target(${superbuild_target} "${CTEST_BINARY_DIRECTORY}")
# runs only tests that have a LABELS property matching "SuperBuild"
func_test("SuperBuild" "${CTEST_BINARY_DIRECTORY}")
endforeach()
# HACK Unfortunately ctest_coverage ignores the build argument, back-up the original dirs
file(READ "${CTEST_BINARY_DIRECTORY}/CMakeFiles/TargetDirectories.txt" old_coverage_dirs)
# explicitly build requested external projects as subprojects
foreach(external_project_with_build_dir ${CTEST_PROJECT_EXTERNALS})
string(REPLACE "^^" ";" external_project_with_build_dir_list "${external_project_with_build_dir}")
list(GET external_project_with_build_dir_list 0 external_project_name)
list(GET external_project_with_build_dir_list 1 external_project_builddir)
set_property(GLOBAL PROPERTY SubProject ${external_project_name})
set_property(GLOBAL PROPERTY Label ${external_project_name})
message("----------- [ Build ${external_project_name} ] -----------")
func_build_target("${external_project_name}" "${CTEST_BINARY_DIRECTORY}")
if(NOT build_errors)
# HACK Unfortunately ctest_coverage ignores the build argument, try to force it...
file(READ "${CTEST_BINARY_DIRECTORY}/${external_project_builddir}/CMakeFiles/TargetDirectories.txt" mitk_build_coverage_dirs)
file(APPEND "${CTEST_BINARY_DIRECTORY}/CMakeFiles/TargetDirectories.txt" "${mitk_build_coverage_dirs}")
message("----------- [ Test ${external_project_name} ] -----------")
# runs only tests that have a LABELS property matching "${external_project_name}"
func_test(${external_project_name} "${CTEST_BINARY_DIRECTORY}/${external_project_builddir}")
# restore old coverage dirs
file(WRITE "${CTEST_BINARY_DIRECTORY}/CMakeFiles/TargetDirectories.txt" "${old_coverage_dirs}")
endif()
endforeach()
# switch back to SuperBuild label
set_property(GLOBAL PROPERTY SubProject SuperBuild)
set_property(GLOBAL PROPERTY Label SuperBuild)
message("----------- [ Finish SuperBuild ] -----------")
else()
message("----------- [ Build SuperBuild ] -----------")
endif()
if(NOT build_errors)
# build everything at superbuild level which has not yet been built
func_build_target("" "${CTEST_BINARY_DIRECTORY}")
endif()
# runs only tests that have a LABELS property matching "SuperBuild"
#func_test("SuperBuild" "${CTEST_BINARY_DIRECTORY}")
set(build_dir "${CTEST_BINARY_DIRECTORY}/${PROJECT_BUILD_DIR}")
if(CTEST_PROJECT_NAME_SUPERBUILD)
set(CTEST_PROJECT_NAME ${ctest_project_name_orig})
endif()
message("----------- [ Configure ${build_dir} ] -----------")
# Configure target
ctest_configure(BUILD "${build_dir}"
OPTIONS "-DCTEST_USE_LAUNCHERS=${CTEST_USE_LAUNCHERS}"
RETURN_VALUE res
)
ctest_read_custom_files("${CTEST_BINARY_DIRECTORY}")
ctest_submit(PARTS Configure RETRY_DELAY 3 RETRY_COUNT 3)
if(res)
math(EXPR build_errors "${build_errors} + 1")
endif()
foreach(subproject ${CTEST_PROJECT_SUBPROJECTS})
if(NOT build_errors)
set_property(GLOBAL PROPERTY SubProject ${subproject})
set_property(GLOBAL PROPERTY Label ${subproject})
if(subproject MATCHES "Unlabeled")
message("----------- [ Build All (Unlabeled) ] -----------")
# Build target
func_build_target("" "${build_dir}")
else()
message("----------- [ Build ${subproject} ] -----------")
# Build target
func_build_target(${subproject} "${build_dir}")
endif()
endif()
endforeach()
if(NOT build_errors)
# HACK Unfortunately ctest_coverage ignores the build argument, try to force it...
file(READ ${build_dir}/CMakeFiles/TargetDirectories.txt mitk_build_coverage_dirs)
file(APPEND "${CTEST_BINARY_DIRECTORY}/CMakeFiles/TargetDirectories.txt" "${mitk_build_coverage_dirs}")
foreach(subproject ${CTEST_PROJECT_SUBPROJECTS})
set_property(GLOBAL PROPERTY SubProject ${subproject})
set_property(GLOBAL PROPERTY Label ${subproject})
message("----------- [ Test ${subproject} ] -----------")
# runs only tests that have a LABELS property matching "${subproject}"
func_test(${subproject} "${build_dir}")
endforeach()
endif()
# Build any additional target which is not build by "all"
# i.e. the "package" target
if(CTEST_PROJECT_ADDITIONAL_TARGETS AND NOT build_errors)
foreach(additional_target ${CTEST_PROJECT_ADDITIONAL_TARGETS})
set_property(GLOBAL PROPERTY SubProject ${additional_target})
set_property(GLOBAL PROPERTY Label ${additional_target})
message("----------- [ Build ${additional_target} ] -----------")
func_build_target(${additional_target} "${build_dir}")
message("----------- [ Test ${additional_target} ] -----------")
# runs only tests that have a LABELS property matching "${subproject}"
func_test(${additional_target} "${build_dir}")
endforeach()
endif()
if(WITH_DOCUMENTATION)
message("----------- [ Build Documentation ] -----------")
set(ctest_use_launchers_orig ${CTEST_USE_LAUNCHERS})
set(CTEST_USE_LAUNCHERS 0)
# Build Documentation target
set_property(GLOBAL PROPERTY SubProject Documentation)
set_property(GLOBAL PROPERTY Label Documentation)
func_build_target("doc" "${build_dir}")
set(CTEST_USE_LAUNCHERS ${ctest_use_launchers_orig})
endif()
set_property(GLOBAL PROPERTY SubProject SuperBuild)
set_property(GLOBAL PROPERTY Label SuperBuild)
# Global coverage ...
if(WITH_COVERAGE AND CTEST_COVERAGE_COMMAND)
message("----------- [ Global coverage ] -----------")
ctest_coverage(BUILD "${build_dir}" APPEND)
ctest_submit(PARTS Coverage RETRY_DELAY 3 RETRY_COUNT 3)
endif()
# Global dynamic analysis ...
if(WITH_MEMCHECK AND CTEST_MEMORYCHECK_COMMAND)
message("----------- [ Global memcheck ] -----------")
ctest_memcheck(BUILD "${build_dir}")
ctest_submit(PARTS MemCheck RETRY_DELAY 3 RETRY_COUNT 3)
endif()
# Note should be at the end
ctest_submit(PARTS Notes RETRY_DELAY 3 RETRY_COUNT 3)
# Send status to the "CDash Web Admin"
if(CDASH_ADMIN_URL_PREFIX)
set(cdash_admin_url "${CDASH_ADMIN_URL_PREFIX}/cdashadmin-web/index.php?pw=4da12ca9c06d46d3171d7f73974c900f")
string(REGEX REPLACE ".*\\?project=(.*)&?" "\\1" _ctest_project "${CTEST_DROP_LOCATION}")
+ string(REPLACE " " "%20" _build_name_escaped "${CTEST_BUILD_NAME}")
file(DOWNLOAD
- "${cdash_admin_url}&action=submit&name=${CTEST_BUILD_NAME}&hasTestErrors=${test_errors}&hasBuildErrors=${build_errors}&hasBuildWarnings=${build_warnings}&ctestDropSite=${CTEST_DROP_SITE}&ctestProject=${_ctest_project}"
+ "${cdash_admin_url}&action=submit&name=${_build_name_escaped}&hasTestErrors=${test_errors}&hasBuildErrors=${build_errors}&hasBuildWarnings=${build_warnings}&ctestDropSite=${CTEST_DROP_SITE}&ctestProject=${_ctest_project}"
"${CTEST_BINARY_DIRECTORY}/cdashadmin.txt"
STATUS status
)
list(GET status 0 error_code)
list(GET status 1 error_msg)
if(error_code)
message(FATAL_ERROR "error: Failed to communicate with cdashadmin-web - ${error_msg}")
endif()
endif()
endif()
# Clear the CTEST_CHECKOUT_COMMAND variable to prevent continuous clients
# to try to checkout again
set(CTEST_CHECKOUT_COMMAND "")
endmacro()
if(SCRIPT_MODE STREQUAL "continuous")
while(1)
run_ctest()
# Loop no faster than once every 5 minutes
message("Wait for 5 minutes ...")
ctest_sleep(300)
endwhile()
else()
run_ctest()
endif()
diff --git a/CMake/MITKDashboardSetup.cmake b/CMake/MITKDashboardSetup.cmake
index 59a8d0eb88..2c544532fb 100644
--- a/CMake/MITKDashboardSetup.cmake
+++ b/CMake/MITKDashboardSetup.cmake
@@ -1,206 +1,207 @@
# This file is intended to be included at the end of a custom MITKDashboardScript.TEMPLATE.cmake file
list(APPEND CTEST_NOTES_FILES "${CTEST_SCRIPT_DIRECTORY}/${CTEST_SCRIPT_NAME}")
#
# Automatically determined properties
#
set(MY_OPERATING_SYSTEM )
if(UNIX)
# Download a utility script
set(url "http://mitk.org/git/?p=MITK.git;a=blob_plain;f=CMake/mitkDetectOS.sh;hb=${hb}")
set(dest "${CTEST_SCRIPT_DIRECTORY}/mitkDetectOS.sh")
downloadFile("${url}" "${dest}")
execute_process(COMMAND sh "${dest}"
RESULT_VARIABLE _result OUTPUT_VARIABLE _out
OUTPUT_STRIP_TRAILING_WHITESPACE)
if(NOT _result)
set(MY_OPERATING_SYSTEM "${_out}")
endif()
endif()
if(NOT MY_OPERATING_SYSTEM)
set(MY_OPERATING_SYSTEM "${CMAKE_HOST_SYSTEM}") # Windows 7, Linux-2.6.32, Darwin...
endif()
site_name(CTEST_SITE)
if(NOT DEFINED MITK_USE_QT)
set(MITK_USE_QT 1)
endif()
if(MITK_USE_QT)
if(NOT QT_QMAKE_EXECUTABLE)
find_program(QT_QMAKE_EXECUTABLE NAMES qmake qmake-qt4
HINTS ${QT_BINARY_DIR})
endif()
execute_process(COMMAND ${QT_QMAKE_EXECUTABLE} --version
OUTPUT_VARIABLE MY_QT_VERSION
RESULT_VARIABLE qmake_error)
if(qmake_error)
message(FATAL_ERROR "Error when executing ${QT_QMAKE_EXECUTABLE} --version\n${qmake_error}")
endif()
string(REGEX REPLACE ".*Qt version ([0-9.]+) .*" "\\1" MY_QT_VERSION ${MY_QT_VERSION})
endif()
#
# Project specific properties
#
if(NOT CTEST_BUILD_NAME)
if(MITK_USE_QT)
set(CTEST_BUILD_NAME "${MY_OPERATING_SYSTEM} ${MY_COMPILER} Qt${MY_QT_VERSION} ${CTEST_BUILD_CONFIGURATION}")
else()
set(CTEST_BUILD_NAME "${MY_OPERATING_SYSTEM} ${MY_COMPILER} ${CTEST_BUILD_CONFIGURATION}")
endif()
+ set(CTEST_BUILD_NAME "${CTEST_BUILD_NAME}${CTEST_BUILD_NAME_SUFFIX}")
endif()
set(PROJECT_BUILD_DIR "MITK-build")
set(CTEST_PATH "$ENV{PATH}")
if(WIN32)
set(ANN_BINARY_DIR "${CTEST_BINARY_DIRECTORY}/ANN-build/${CTEST_BUILD_CONFIGURATION}")
set(CPPUNIT_BINARY_DIR "${CTEST_BINARY_DIRECTORY}/CppUnit-build/${CTEST_BUILD_CONFIGURATION}")
set(GLUT_BINARY_DIR "${CTEST_BINARY_DIRECTORY}/GLUT-build/${CTEST_BUILD_CONFIGURATION}")
set(GLEW_BINARY_DIR "${CTEST_BINARY_DIRECTORY}/GLEW-build/${CTEST_BUILD_CONFIGURATION}")
set(TINYXML_BINARY_DIR "${CTEST_BINARY_DIRECTORY}/tinyxml-build/${CTEST_BUILD_CONFIGURATION}")
set(QWT_BINARY_DIR "${CTEST_BINARY_DIRECTORY}/Qwt-build/${CTEST_BUILD_CONFIGURATION}")
set(VTK_BINARY_DIR "${CTEST_BINARY_DIRECTORY}/VTK-build/bin/${CTEST_BUILD_CONFIGURATION}")
set(ACVD_BINARY_DIR "${CTEST_BINARY_DIRECTORY}/ACVD-build/bin/${CTEST_BUILD_CONFIGURATION}")
set(ITK_BINARY_DIR "${CTEST_BINARY_DIRECTORY}/ITK-build/bin/${CTEST_BUILD_CONFIGURATION}")
set(BOOST_BINARY_DIR "${CTEST_BINARY_DIRECTORY}/Boost-install/lib")
set(GDCM_BINARY_DIR "${CTEST_BINARY_DIRECTORY}/GDCM-build/bin/${CTEST_BUILD_CONFIGURATION}")
set(DCMTK_BINARY_DIR "${CTEST_BINARY_DIRECTORY}/DCMTK-install/bin/${CTEST_BUILD_CONFIGURATION}")
set(OPENCV_BINARY_DIR "${CTEST_BINARY_DIRECTORY}/OpenCV-build/bin/${CTEST_BUILD_CONFIGURATION}")
set(POCO_BINARY_DIR "${CTEST_BINARY_DIRECTORY}/Poco-install/lib")
set(SOFA_BINARY_DIR "${CTEST_BINARY_DIRECTORY}/SOFA-build/bin/${CTEST_BUILD_CONFIGURATION}")
set(BLUEBERRY_OSGI_DIR "${CTEST_BINARY_DIRECTORY}/MITK-build/bin/BlueBerry/org.blueberry.osgi/bin/${CTEST_BUILD_CONFIGURATION}")
set(CTEST_PATH "${CTEST_PATH};${CPPUNIT_BINARY_DIR};${QT_BINARY_DIR};${VTK_BINARY_DIR};${ANN_BINARY_DIR};${GLUT_BINARY_DIR};${GLEW_BINARY_DIR};${TINYXML_BINARY_DIR};${QWT_BINARY_DIR};${ACVD_BINARY_DIR};${ITK_BINARY_DIR};${BOOST_BINARY_DIR};${GDCM_BINARY_DIR};${DCMTK_BINARY_DIR};${OPENCV_BINARY_DIR};${POCO_BINARY_DIR};${SOFA_BINARY_DIR};${BLUEBERRY_OSGI_DIR}")
endif()
set(ENV{PATH} "${CTEST_PATH}")
set(SUPERBUILD_TARGETS "")
# If the dashscript doesn't define a GIT_REPOSITORY variable, let's define it here.
if(NOT DEFINED GIT_REPOSITORY OR GIT_REPOSITORY STREQUAL "")
set(GIT_REPOSITORY "http://git.mitk.org/MITK.git")
endif()
#
# Display build info
#
message("Site name: ${CTEST_SITE}")
message("Build name: ${CTEST_BUILD_NAME}")
message("Script Mode: ${SCRIPT_MODE}")
message("Coverage: ${WITH_COVERAGE}, MemCheck: ${WITH_MEMCHECK}")
#
# Set initial cache options
#
if(${CMAKE_VERSION} VERSION_GREATER "2.8.9")
set(CTEST_USE_LAUNCHERS 1)
set(ENV{CTEST_USE_LAUNCHERS_DEFAULT} 1)
endif()
# Remove this if block after all dartclients work
if(DEFINED ADDITIONNAL_CMAKECACHE_OPTION)
message(WARNING "Rename ADDITIONNAL to ADDITIONAL in your dartlclient script: ${CTEST_SCRIPT_DIRECTORY}/${CTEST_SCRIPT_NAME}")
set(ADDITIONAL_CMAKECACHE_OPTION ${ADDITIONNAL_CMAKECACHE_OPTION})
endif()
if(NOT DEFINED MITK_USE_ACVD)
set(MITK_USE_ACVD 1)
endif()
if(NOT DEFINED MITK_USE_Boost)
set(MITK_USE_Boost 1)
endif()
if(NOT DEFINED MITK_USE_OpenCV)
set(MITK_USE_OpenCV 1)
endif()
if(NOT DEFINED MITK_USE_Poco)
set(MITK_USE_Poco 1)
endif()
if(NOT DEFINED MITK_USE_Python)
if(WIN32)
set(MITK_USE_Python FALSE)
else()
set(MITK_USE_Python TRUE)
endif()
endif()
if(NOT DEFINED MITK_USE_SOFA)
set(MITK_USE_SOFA 1)
endif()
if(NOT DEFINED MITK_VTK_DEBUG_LEAKS)
set(MITK_VTK_DEBUG_LEAKS 1)
endif()
if(NOT DEFINED MITK_BUILD_ALL_APPS)
set(MITK_BUILD_ALL_APPS TRUE)
endif()
if(NOT DEFINED BLUEBERRY_BUILD_ALL_PLUGINS)
set(BLUEBERRY_BUILD_ALL_PLUGINS TRUE)
endif()
if(NOT DEFINED MITK_BUILD_ALL_PLUGINS)
set(MITK_BUILD_ALL_PLUGINS TRUE)
endif()
if(NOT DEFINED MITK_BUILD_EXAMPLES)
set(MITK_BUILD_EXAMPLES TRUE)
endif()
if(NOT BUILD_DiffusionMiniApps)
set(BUILD_DiffusionMiniApps TRUE)
endif()
set(INITIAL_CMAKECACHE_OPTIONS "
BLUEBERRY_BUILD_ALL_PLUGINS:BOOL=${MITK_BUILD_ALL_PLUGINS}
MITK_BUILD_ALL_PLUGINS:BOOL=${MITK_BUILD_ALL_PLUGINS}
MITK_BUILD_ALL_APPS:BOOL=${MITK_BUILD_ALL_APPS}
MITK_BUILD_EXAMPLES:BOOL=${MITK_BUILD_EXAMPLES}
SUPERBUILD_EXCLUDE_MITKBUILD_TARGET:BOOL=TRUE
MITK_USE_ACVD:BOOL=${MITK_USE_ACVD}
MITK_USE_Boost:BOOL=${MITK_USE_Boost}
MITK_USE_OpenCV:BOOL=${MITK_USE_OpenCV}
MITK_USE_Poco:BOOL=${MITK_USE_Poco}
MITK_USE_Python:BOOL=${MITK_USE_Python}
MITK_USE_SOFA:BOOL=${MITK_USE_SOFA}
MITK_USE_QT:BOOL=${MITK_USE_QT}
MITK_VTK_DEBUG_LEAKS:BOOL=${MITK_VTK_DEBUG_LEAKS}
${ADDITIONAL_CMAKECACHE_OPTION}
")
if(MITK_USE_QT)
set(INITIAL_CMAKECACHE_OPTIONS "${INITIAL_CMAKECACHE_OPTIONS}
QT_QMAKE_EXECUTABLE:FILEPATH=${QT_QMAKE_EXECUTABLE}")
endif()
# Write a cache file for populating the MITK initial cache (not the superbuild cache).
# This can be used to provide variables which are not passed through the
# superbuild process to the MITK configure step)
if(MITK_INITIAL_CACHE)
set(mitk_cache_file "${CTEST_SCRIPT_DIRECTORY}/mitk_initial_cache.txt")
file(WRITE "${mitk_cache_file}" "${MITK_INITIAL_CACHE}")
set(INITIAL_CMAKECACHE_OPTIONS "${INITIAL_CMAKECACHE_OPTIONS}
MITK_INITIAL_CACHE_FILE:INTERNAL=${mitk_cache_file}
")
endif()
#
# Download and include dashboard driver script
#
set(url "http://mitk.org/git/?p=MITK.git;a=blob_plain;f=CMake/MITKDashboardDriverScript.cmake;hb=${hb}")
set(dest ${CTEST_SCRIPT_DIRECTORY}/${CTEST_SCRIPT_NAME}.driver)
downloadFile("${url}" "${dest}")
include(${dest})
diff --git a/CMake/PackageDepends/MITK_Boost_Config.cmake b/CMake/PackageDepends/MITK_Boost_Config.cmake
index 1f2eb572f2..0414b37a77 100644
--- a/CMake/PackageDepends/MITK_Boost_Config.cmake
+++ b/CMake/PackageDepends/MITK_Boost_Config.cmake
@@ -1,29 +1,29 @@
if(MITK_USE_Boost)
if(NOT MITK_USE_SYSTEM_Boost)
set(Boost_NO_SYSTEM_PATHS 1)
endif()
set(Boost_USE_MULTITHREADED 1)
set(Boost_USE_STATIC_LIBS 0)
set(Boost_USE_STATIC_RUNTIME 0)
if(MITK_USE_Boost_LIBRARIES)
if(NOT MITK_USE_SYSTEM_Boost)
set(BOOST_INCLUDEDIR ${CMAKE_BINARY_DIR}/../Boost-install/include)
set(BOOST_LIBRARYDIR ${CMAKE_BINARY_DIR}/../Boost-install/lib)
- set(Boost_ADDITIONAL_VERSIONS 1.55)
+ set(Boost_ADDITIONAL_VERSIONS 1.56)
endif()
- find_package(Boost 1.55.0 REQUIRED COMPONENTS ${MITK_USE_Boost_LIBRARIES} QUIET)
+ find_package(Boost 1.56.0 REQUIRED COMPONENTS ${MITK_USE_Boost_LIBRARIES} QUIET)
else()
- find_package(Boost 1.55.0 REQUIRED QUIET)
+ find_package(Boost 1.56.0 REQUIRED QUIET)
endif()
list(APPEND ALL_INCLUDE_DIRECTORIES ${Boost_INCLUDE_DIRS})
if(Boost_LIBRARIES)
list(APPEND ALL_LIBRARIES ${Boost_LIBRARIES})
link_directories(${Boost_LIBRARY_DIRS})
endif()
endif(MITK_USE_Boost)
diff --git a/CMake/PackageDepends/MITK_Eigen_Config.cmake b/CMake/PackageDepends/MITK_Eigen_Config.cmake
new file mode 100644
index 0000000000..dfd8299dd7
--- /dev/null
+++ b/CMake/PackageDepends/MITK_Eigen_Config.cmake
@@ -0,0 +1 @@
+list(APPEND ALL_INCLUDE_DIRECTORIES ${Eigen_DIR}/include/eigen3)
diff --git a/CMake/QBundleTemplate/documentation/Manual/Manual.dox b/CMake/QBundleTemplate/documentation/Manual/Manual.dox
index 7b764026fa..21d82fb187 100755
--- a/CMake/QBundleTemplate/documentation/Manual/Manual.dox
+++ b/CMake/QBundleTemplate/documentation/Manual/Manual.dox
@@ -1,13 +1,12 @@
/**
-\page @PLUGIN_ID@ @PLUGIN_NAME@
+\page @PLUGIN_ID@ The @PLUGIN_NAME@
\imageMacro{icon.png,"Icon of @PLUGIN_NAME@",2.00}
-Available sections:
- - \ref @PLUGIN_ID@Overview
+\tableofcontents
-\section @PLUGIN_ID@Overview
+\section @PLUGIN_ID@Overview Overview
This is the description for the @PLUGIN_NAME@.
*/
diff --git a/CMake/mitkFunctionCreateModule.cmake b/CMake/mitkFunctionCreateModule.cmake
index 6b56cc13c4..3c4df77d3f 100644
--- a/CMake/mitkFunctionCreateModule.cmake
+++ b/CMake/mitkFunctionCreateModule.cmake
@@ -1,602 +1,612 @@
function(_link_directories_for_packages)
set(ALL_LIBRARY_DIRS )
foreach(package ${ARGN})
if(NOT ${package} MATCHES "^(Qt[45].*|ITK|VTK)$")
foreach(dir ${MODULES_PACKAGE_DEPENDS_DIRS})
if(EXISTS "${dir}/MITK_${package}_Config.cmake")
include("${dir}/MITK_${package}_Config.cmake")
break()
endif()
endforeach()
endif()
endforeach()
if(ALL_LIBRARY_DIRS)
list(REMOVE_DUPLICATES ALL_LIBRARY_DIRS)
link_directories(${ALL_LIBRARY_DIRS})
endif()
endfunction()
##################################################################
#
# mitk_create_module
#
#! Creates a module for the automatic module dependency system within MITK.
#! Configurations are generated in the moduleConf directory.
#!
#! USAGE:
#!
#! \code
#! MITK_CREATE_MODULE([]
#! [INCLUDE_DIRS ]
#! [INTERNAL_INCLUDE_DIRS ]
#! [DEPENDS ]
#! [PACKAGE_DEPENDS ]
#! [TARGET_DEPENDS
#! [EXPORT_DEFINE ]
#! [QT_MODULE]
#! [HEADERS_ONLY]
#! [WARNINGS_AS_ERRORS]
#! \endcode
#!
#! The parameter specifies the name of the module which is used
#! create a logical target name. The parameter is options in case the
#! MITK_MODULE_NAME_DEFAULTS_TO_DIRECTORY_NAME variable evaluates to TRUE. The
#! module name will then be derived from the directory name in which this
#! macro is called.
#!
#! If set, the following variables will be used to validate the module name:
#!
#! MITK_MODULE_NAME_REGEX_MATCH The module name must match this regular expression.
#! MITK_MODULE_NAME_REGEX_NOT_MATCH The module name must not match this regular expression.
#!
#! If the MITK_MODULE_NAME_PREFIX variable is set, the module name will be prefixed
#! with its contents.
#!
#! A modules source files are specified in a separate CMake file usually
#! called files.cmake, located in the module root directory. The
#! mitk_create_module() macro evaluates the following CMake variables
#! from the files.cmake file:
#!
#! - CPP_FILES A list of .cpp files
#! - H_FILES A list of .h files without a corresponding .cpp file
#! - TXX_FILES A list of .txx files
#! - RESOURCE_FILES A list of files (resources) which are embedded into the module
#! - MOC_H_FILES A list of Qt header files which should be processed by the MOC
#! - UI_FILES A list of .ui Qt UI files
#! - QRC_FILES A list of .qrc Qt resource files
#! - DOX_FILES A list of .dox Doxygen files
#!
#! List of variables available after the function is called:
#! - MODULE_NAME
#! - MODULE_TARGET
#! - MODULE_IS_ENABLED
#! - MODULE_SUBPROJECTS
#! - ALL_META_DEPENDENCIES
#!
#! \param QT_MODULE deprecated. Just use Qt4 or Qt5 in the PACKAGE_DEPENDS argument.
#! \param HEADERS_ONLY specify this if the modules just contains header files.
##################################################################
function(mitk_create_module)
set(_macro_params
SUBPROJECTS # list of CDash labels
VERSION # module version number, e.g. "1.2.0"
INCLUDE_DIRS # exported include dirs (used in mitkMacroCreateModuleConf.cmake)
INTERNAL_INCLUDE_DIRS # include dirs internal to this module
DEPENDS # list of modules this module depends on
DEPENDS_INTERNAL # list of modules this module internally depends on
PACKAGE_DEPENDS # list of "packages this module depends on (e.g. Qt, VTK, etc.)
TARGET_DEPENDS # list of CMake targets this module should depend on
EXPORT_DEFINE # export macro name for public symbols of this module
AUTOLOAD_WITH # a module target name identifying the module which will trigger the
# automatic loading of this module
ADDITIONAL_LIBS # list of addidtional libraries linked to this module
FILES_CMAKE # file name of a CMake file setting source list variables
# (defaults to files.cmake)
GENERATED_CPP # not used (?)
DEPRECATED_SINCE # marks this modules as deprecated
DESCRIPTION # a description for this module
)
set(_macro_options
QT_MODULE # the module makes use of Qt4 features and needs moc and ui generated files
FORCE_STATIC # force building this module as a static library
HEADERS_ONLY # this module is a headers-only library
GCC_DEFAULT_VISIBILITY # do not use gcc visibility flags - all symbols will be exported
NO_INIT # do not create CppMicroServices initialization code
NO_FEATURE_INFO # do not create a feature info by calling add_feature_info()
WARNINGS_AS_ERRORS # treat all compiler warnings as errors
EXECUTABLE # create an executable; do not use directly, use mitk_create_executable() instead
)
MACRO_PARSE_ARGUMENTS(MODULE "${_macro_params}" "${_macro_options}" ${ARGN})
set(MODULE_NAME ${MODULE_DEFAULT_ARGS})
if(NOT MODULE_NAME)
if(MITK_MODULE_NAME_DEFAULTS_TO_DIRECTORY_NAME)
get_filename_component(MODULE_NAME ${CMAKE_CURRENT_SOURCE_DIR} NAME)
else()
message(SEND_ERROR "The module name must not be empty")
endif()
endif()
+ set(_module_type module)
+ set(_Module_type Module)
+ if(MODULE_EXECUTABLE)
+ set(_module_type executable)
+ set(_Module_type Executable)
+ endif()
+
if(MITK_MODULE_NAME_REGEX_MATCH)
if(NOT ${MODULE_NAME} MATCHES ${MITK_MODULE_NAME_REGEX_MATCH})
- message(SEND_ERROR "The module name \"${MODULE_NAME}\" does not match the regular expression \"${MITK_MODULE_NAME_REGEX_MATCH}\".")
+ message(SEND_ERROR "The ${_module_type} name \"${MODULE_NAME}\" does not match the regular expression \"${MITK_MODULE_NAME_REGEX_MATCH}\".")
endif()
endif()
if(MITK_MODULE_NAME_REGEX_NOT_MATCH)
if(${MODULE_NAME} MATCHES ${MITK_MODULE_NAME_REGEX_NOT_MATCH})
- message(SEND_ERROR "The module name \"${MODULE_NAME}\" must not match the regular expression \"${MITK_MODULE_NAME_REGEX_NOT_MATCH}\".")
+ message(SEND_ERROR "The ${_module_type} name \"${MODULE_NAME}\" must not match the regular expression \"${MITK_MODULE_NAME_REGEX_NOT_MATCH}\".")
endif()
endif()
if(MITK_MODULE_NAME_PREFIX AND NOT MODULE_NAME MATCHES "^${MITK_MODULE_NAME_PREFIX}.*$")
set(MODULE_NAME "${MITK_MODULE_NAME_PREFIX}${MODULE_NAME}")
endif()
if(NOT MODULE_FILES_CMAKE)
set(MODULE_FILES_CMAKE files.cmake)
endif()
if(NOT IS_ABSOLUTE ${MODULE_FILES_CMAKE})
set(MODULE_FILES_CMAKE ${CMAKE_CURRENT_SOURCE_DIR}/${MODULE_FILES_CMAKE})
endif()
if (MODULE_QT_MODULE)
- message(WARNING "QT_MODULE keyword is deprecated (in module ${MODULE_NAME}). Please use PACKAGE_DEPENDS Qt4|QtCore and/or PACKAGE_DEPENDS Qt5|Core instead")
+ message(WARNING "QT_MODULE keyword is deprecated (in ${_module_type} ${MODULE_NAME}). Please use PACKAGE_DEPENDS Qt4|QtCore and/or PACKAGE_DEPENDS Qt5|Core instead")
if (NOT "${MODULE_PACKAGE_DEPENDS}" MATCHES "^.*Qt4.*$")
list(APPEND MODULE_PACKAGE_DEPENDS Qt4|QtGui)
endif()
endif()
if(MODULE_HEADERS_ONLY)
set(MODULE_TARGET )
if(MODULE_AUTOLOAD_WITH)
message(SEND_ERROR "A headers only module cannot be auto-loaded")
endif()
else()
set(MODULE_TARGET ${MODULE_NAME})
endif()
if(MODULE_DEPRECATED_SINCE)
set(MODULE_IS_DEPRECATED 1)
else()
set(MODULE_IS_DEPRECATED 0)
endif()
if(NOT MODULE_SUBPROJECTS)
if(MITK_DEFAULT_SUBPROJECTS)
set(MODULE_SUBPROJECTS ${MITK_DEFAULT_SUBPROJECTS})
endif()
endif()
# check if the subprojects exist as targets
if(MODULE_SUBPROJECTS)
foreach(subproject ${MODULE_SUBPROJECTS})
if(NOT TARGET ${subproject})
message(SEND_ERROR "The subproject ${subproject} does not have a corresponding target")
endif()
endforeach()
endif()
# assume worst case
set(MODULE_IS_ENABLED 0)
# first we check if we have an explicit module build list
if(MITK_MODULES_TO_BUILD)
list(FIND MITK_MODULES_TO_BUILD ${MODULE_NAME} _MOD_INDEX)
if(_MOD_INDEX EQUAL -1)
set(MODULE_IS_EXCLUDED 1)
endif()
endif()
if(NOT MODULE_IS_EXCLUDED)
# first of all we check for the dependencies
_mitk_parse_package_args(${MODULE_PACKAGE_DEPENDS})
mitk_check_module_dependencies(MODULES ${MODULE_DEPENDS}
PACKAGES ${PACKAGE_NAMES}
MISSING_DEPENDENCIES_VAR _MISSING_DEP
PACKAGE_DEPENDENCIES_VAR PACKAGE_NAMES)
if(_MISSING_DEP)
if(MODULE_NO_FEATURE_INFO)
- message("Module ${MODULE_NAME} won't be built, missing dependency: ${_MISSING_DEP}")
+ message("${_Module_type} ${MODULE_NAME} won't be built, missing dependency: ${_MISSING_DEP}")
endif()
set(MODULE_IS_ENABLED 0)
else()
set(MODULE_IS_ENABLED 1)
# now check for every package if it is enabled. This overlaps a bit with
# MITK_CHECK_MODULE ...
foreach(_package ${PACKAGE_NAMES})
if((DEFINED MITK_USE_${_package}) AND NOT (MITK_USE_${_package}))
- message("Module ${MODULE_NAME} won't be built. Turn on MITK_USE_${_package} if you want to use it.")
+ message("${_Module_type} ${MODULE_NAME} won't be built. Turn on MITK_USE_${_package} if you want to use it.")
set(MODULE_IS_ENABLED 0)
break()
endif()
endforeach()
if(MODULE_IS_ENABLED)
# clear variables defined in files.cmake
set(RESOURCE_FILES )
set(CPP_FILES )
set(H_FILES )
set(TXX_FILES )
set(DOX_FILES )
set(UI_FILES )
set(MOC_H_FILES )
set(QRC_FILES )
# clear other variables
set(Q${KITNAME}_GENERATED_CPP )
set(Q${KITNAME}_GENERATED_MOC_CPP )
set(Q${KITNAME}_GENERATED_QRC_CPP )
set(Q${KITNAME}_GENERATED_UI_CPP )
# check and set-up auto-loading
if(MODULE_AUTOLOAD_WITH)
if(NOT TARGET "${MODULE_AUTOLOAD_WITH}")
message(SEND_ERROR "The module target \"${MODULE_AUTOLOAD_WITH}\" specified as the auto-loading module for \"${MODULE_NAME}\" does not exist")
endif()
set(_module_autoload_meta_target "${MODULE_AUTOLOAD_WITH}-autoload")
# create a meta-target if it does not already exist
if(NOT TARGET ${_module_autoload_meta_target})
add_custom_target(${_module_autoload_meta_target})
endif()
endif()
# Convert relative include dirs to absolute dirs
set(_include_dirs . ${MODULE_INCLUDE_DIRS})
set(MODULE_INCLUDE_DIRS)
foreach(dir ${_include_dirs})
get_filename_component(_abs_dir ${dir} ABSOLUTE)
list(APPEND MODULE_INCLUDE_DIRS ${_abs_dir})
endforeach()
list(APPEND MODULE_INCLUDE_DIRS ${MITK_BINARY_DIR} ${MODULES_CONF_DIRS})
# Convert relative internal include dirs to absolute dirs
set(_include_dirs ${MODULE_INTERNAL_INCLUDE_DIRS})
set(MODULE_INTERNAL_INCLUDE_DIRS)
foreach(dir ${_include_dirs})
get_filename_component(_abs_dir ${dir} ABSOLUTE)
list(APPEND MODULE_INTERNAL_INCLUDE_DIRS ${_abs_dir})
endforeach()
# Qt generates headers in the binary tree
list(APPEND MODULE_INCLUDE_DIRS ${CMAKE_CURRENT_BINARY_DIR})
# Add the module specific include dirs
include_directories(${MODULE_INCLUDE_DIRS} ${MODULE_INTERNAL_INCLUDE_DIRS})
if(NOT MODULE_EXECUTABLE)
_MITK_CREATE_MODULE_CONF()
endif()
if(NOT MODULE_EXPORT_DEFINE)
set(MODULE_EXPORT_DEFINE ${MODULE_NAME}_EXPORT)
endif(NOT MODULE_EXPORT_DEFINE)
if(MITK_GENERATE_MODULE_DOT)
message("MODULEDOTNAME ${MODULE_NAME}")
foreach(dep ${MODULE_DEPENDS})
message("MODULEDOT \"${MODULE_NAME}\" -> \"${dep}\" ; ")
endforeach(dep)
endif(MITK_GENERATE_MODULE_DOT)
# ok, now create the module itself
include(${MODULE_FILES_CMAKE})
set(module_c_flags )
set(module_c_flags_debug )
set(module_c_flags_release )
set(module_cxx_flags )
set(module_cxx_flags_debug )
set(module_cxx_flags_release )
if(MODULE_GCC_DEFAULT_VISIBILITY)
set(use_visibility_flags 0)
else()
# We only support hidden visibility for gcc for now. Clang 3.0 still has troubles with
# correctly marking template declarations and explicit template instantiations as exported.
# See http://comments.gmane.org/gmane.comp.compilers.clang.scm/50028
# and http://llvm.org/bugs/show_bug.cgi?id=10113
if(CMAKE_COMPILER_IS_GNUCXX)
set(use_visibility_flags 1)
else()
# set(use_visibility_flags 0)
endif()
endif()
if(CMAKE_COMPILER_IS_GNUCXX)
# MinGW does not export all symbols automatically, so no need to set flags.
#
# With gcc < 4.5, RTTI symbols from classes declared in third-party libraries
# which are not "gcc visibility aware" are marked with hidden visibility in
# DSOs which include the class declaration and which are compiled with
# hidden visibility. This leads to dynamic_cast and exception handling problems.
# While this problem could be worked around by sandwiching the include
# directives for the third-party headers between "#pragma visibility push/pop"
# statements, it is generally safer to just use default visibility with
# gcc < 4.5.
if(${GCC_VERSION} VERSION_LESS "4.5" OR MINGW)
set(use_visibility_flags 0)
endif()
endif()
if(use_visibility_flags)
mitkFunctionCheckCAndCXXCompilerFlags("-fvisibility=hidden" module_c_flags module_cxx_flags)
mitkFunctionCheckCAndCXXCompilerFlags("-fvisibility-inlines-hidden" module_c_flags module_cxx_flags)
endif()
configure_file(${MITK_SOURCE_DIR}/CMake/moduleExports.h.in ${CMAKE_BINARY_DIR}/${MODULES_CONF_DIRNAME}/${MODULE_NAME}Exports.h @ONLY)
if(MODULE_WARNINGS_AS_ERRORS)
if(MSVC_VERSION)
mitkFunctionCheckCAndCXXCompilerFlags("/WX" module_c_flags module_cxx_flags)
else()
mitkFunctionCheckCAndCXXCompilerFlags("-Werror" module_c_flags module_cxx_flags)
# The flag "c++0x-static-nonintegral-init" has been renamed in newer Clang
# versions to "static-member-init", see
# http://clang-developers.42468.n3.nabble.com/Wc-0x-static-nonintegral-init-gone-td3999651.html
#
# Also, older Clang and seemingly all gcc versions do not warn if unknown
# "-no-*" flags are used, so CMake will happily append any -Wno-* flag to the
# command line. This may get confusing if unrelated compiler errors happen and
# the error output then additionally contains errors about unknown flags (which
# is not the case if there were no compile errors).
#
# So instead of using -Wno-* we use -Wno-error=*, which will be properly rejected by
# the compiler and if applicable, prints the specific warning as a real warning and
# not as an error (although -Werror was given).
mitkFunctionCheckCAndCXXCompilerFlags("-Wno-error=c++0x-static-nonintegral-init" module_c_flags module_cxx_flags)
mitkFunctionCheckCAndCXXCompilerFlags("-Wno-error=static-member-init" module_c_flags module_cxx_flags)
mitkFunctionCheckCAndCXXCompilerFlags("-Wno-error=unknown-warning" module_c_flags module_cxx_flags)
mitkFunctionCheckCAndCXXCompilerFlags("-Wno-error=gnu" module_c_flags module_cxx_flags)
# VNL headers throw a lot of these, not fixable for us at least in ITK 3
mitkFunctionCheckCAndCXXCompilerFlags("-Wno-error=unused-parameter" module_c_flags module_cxx_flags)
# Some DICOM header file in ITK
mitkFunctionCheckCAndCXXCompilerFlags("-Wno-error=cast-align" module_c_flags module_cxx_flags)
endif()
endif(MODULE_WARNINGS_AS_ERRORS)
if(MODULE_FORCE_STATIC)
set(_STATIC STATIC)
else()
set(_STATIC )
endif(MODULE_FORCE_STATIC)
# create a meta-target for auto-loaded modules
add_custom_target(${MODULE_NAME}-autoload)
if(NOT MODULE_HEADERS_ONLY)
- if(NOT MODULE_NO_INIT)
+ if(NOT MODULE_NO_INIT OR RESOURCE_FILES)
find_package(CppMicroServices QUIET NO_MODULE REQUIRED)
- if(MODULE_EXECUTABLE)
- usFunctionGenerateExecutableInit(CPP_FILES
- IDENTIFIER ${MODULE_TARGET}
- )
- else()
- usFunctionGenerateModuleInit(CPP_FILES
- NAME ${MODULE_NAME}
- LIBRARY_NAME ${MODULE_TARGET}
- )
- endif()
+ endif()
+ if(NOT MODULE_NO_INIT)
+ usFunctionGenerateModuleInit(CPP_FILES)
endif()
+ set(binary_res_files )
+ set(source_res_files )
if(RESOURCE_FILES)
set(res_dir Resources)
- set(binary_res_files )
- set(source_res_files )
foreach(res_file ${RESOURCE_FILES})
if(EXISTS ${CMAKE_CURRENT_BINARY_DIR}/${res_dir}/${res_file})
list(APPEND binary_res_files "${res_file}")
else()
list(APPEND source_res_files "${res_file}")
endif()
endforeach()
- set(res_macro_args )
- if(binary_res_files)
- list(APPEND res_macro_args ROOT_DIR ${CMAKE_CURRENT_BINARY_DIR}/${res_dir}
- FILES ${binary_res_files})
- endif()
+ # Add a source level dependencies on resource files
if(source_res_files)
- list(APPEND res_macro_args ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/${res_dir}
- FILES ${source_res_files})
+ list(APPEND CPP_FILES ${MODULE_TARGET}_resources.cpp)
+ endif()
+ if(binary_res_files)
+ list(APPEND CPP_FILES ${CMAKE_CURRENT_BINARY_DIR}/${MODULE_TARGET}_binary_resources.cpp)
endif()
-
- usFunctionEmbedResources(CPP_FILES
- LIBRARY_NAME ${MODULE_TARGET}
- ${res_macro_args})
endif()
-
endif()
# Qt 4 case
if(MITK_USE_Qt4)
if(UI_FILES)
qt4_wrap_ui(Q${KITNAME}_GENERATED_UI_CPP ${UI_FILES})
endif()
if(MOC_H_FILES)
qt4_wrap_cpp(Q${KITNAME}_GENERATED_MOC_CPP ${MOC_H_FILES} OPTIONS -DBOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
endif()
if(QRC_FILES)
qt4_add_resources(Q${KITNAME}_GENERATED_QRC_CPP ${QRC_FILES})
endif()
endif()
# all the same for Qt 5
if(MITK_USE_Qt5)
if(UI_FILES)
qt5_wrap_ui(Q${KITNAME}_GENERATED_UI_CPP ${UI_FILES})
endif()
if(MOC_H_FILES)
qt5_wrap_cpp(Q${KITNAME}_GENERATED_MOC_CPP ${MOC_H_FILES} OPTIONS -DBOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
endif()
if(QRC_FILES)
qt5_add_resources(Q${KITNAME}_GENERATED_QRC_CPP ${QRC_FILES})
endif()
endif()
set(Q${KITNAME}_GENERATED_CPP ${Q${KITNAME}_GENERATED_CPP} ${Q${KITNAME}_GENERATED_UI_CPP} ${Q${KITNAME}_GENERATED_MOC_CPP} ${Q${KITNAME}_GENERATED_QRC_CPP})
ORGANIZE_SOURCES(SOURCE ${CPP_FILES}
HEADER ${H_FILES}
TXX ${TXX_FILES}
DOC ${DOX_FILES}
UI ${UI_FILES}
QRC ${QRC_FILES}
MOC ${Q${KITNAME}_GENERATED_MOC_CPP}
GEN_QRC ${Q${KITNAME}_GENERATED_QRC_CPP}
GEN_UI ${Q${KITNAME}_GENERATED_UI_CPP})
set(coverage_sources
${CPP_FILES} ${H_FILES} ${GLOBBED__H_FILES} ${CORRESPONDING__H_FILES} ${TXX_FILES}
${TOOL_CPPS} ${TOOL_GUI_CPPS})
if(MODULE_SUBPROJECTS)
set_property(SOURCE ${coverage_sources} APPEND PROPERTY LABELS ${MODULE_SUBPROJECTS} MITK)
endif()
if(NOT MODULE_HEADERS_ONLY)
# We have to include the MITK__Config.cmake files here because
# some external packages do not provide exported targets with an
# absolute path to link to. So we need to add link directories *before*
# add_library() or add_executable() is called. So far, this is needed only
# for GDCM and ACVD.
_link_directories_for_packages(${PACKAGE_NAMES})
# Apply properties to the module target.
# We cannot use set_target_properties like below since there is no way to
# differentiate C/C++ and Releas/Debug flags using target properties.
# See http://www.cmake.org/Bug/view.php?id=6493
#set_target_properties(${MODULE_TARGET} PROPERTIES
# COMPILE_FLAGS "${module_compile_flags}")
#
# Strangely, we need to set the variables below in the parent scope
# (outside of the function) to be picked up by the target.
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${module_c_flags}" PARENT_SCOPE)
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} ${module_c_flags_debug}" PARENT_SCOPE)
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} ${module_c_flags_release}" PARENT_SCOPE)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${module_cxx_flags}" PARENT_SCOPE)
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} ${module_cxx_flags_debug}" PARENT_SCOPE)
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} ${module_cxx_flags_release}" PARENT_SCOPE)
if(MODULE_EXECUTABLE)
add_executable(${MODULE_TARGET}
${coverage_sources} ${CPP_FILES_GENERATED} ${Q${KITNAME}_GENERATED_CPP}
${DOX_FILES} ${UI_FILES} ${QRC_FILES})
+ set(_us_module_name main)
else()
add_library(${MODULE_TARGET} ${_STATIC}
${coverage_sources} ${CPP_FILES_GENERATED} ${Q${KITNAME}_GENERATED_CPP}
${DOX_FILES} ${UI_FILES} ${QRC_FILES})
+ set(_us_module_name ${MODULE_TARGET})
endif()
+ set_property(TARGET ${MODULE_TARGET} APPEND PROPERTY COMPILE_DEFINITIONS US_MODULE_NAME=${_us_module_name})
+ set_property(TARGET ${MODULE_TARGET} PROPERTY US_MODULE_NAME ${_us_module_name})
if(MODULE_TARGET_DEPENDS)
add_dependencies(${MODULE_TARGET} ${MODULE_TARGET_DEPENDS})
endif()
if(MODULE_SUBPROJECTS)
set_property(TARGET ${MODULE_TARGET} PROPERTY LABELS ${MODULE_SUBPROJECTS} MITK)
foreach(subproject ${MODULE_SUBPROJECTS})
add_dependencies(${subproject} ${MODULE_TARGET})
endforeach()
endif()
set(DEPENDS "${MODULE_DEPENDS}")
if(NOT MODULE_NO_INIT)
# Add a CppMicroServices dependency implicitly, since it is
# needed for the generated "module initialization" code.
set(DEPENDS "CppMicroServices;${DEPENDS}")
endif()
if(DEPENDS OR MODULE_PACKAGE_DEPENDS)
mitk_use_modules(TARGET ${MODULE_TARGET}
MODULES ${DEPENDS}
PACKAGES ${MODULE_PACKAGE_DEPENDS}
)
endif()
if(MINGW)
target_link_libraries(${MODULE_TARGET} ssp) # add stack smash protection lib
endif()
# Add additional library search directories to a global property which
# can be evaluated by other CMake macros, e.g. our install scripts.
if(MODULE_ADDITIONAL_LIBS)
target_link_libraries(${MODULE_TARGET} ${MODULE_ADDITIONAL_LIBS})
get_property(_mitk_additional_library_search_paths GLOBAL PROPERTY MITK_ADDITIONAL_LIBRARY_SEARCH_PATHS)
foreach(_lib_filepath ${MODULE_ADDITIONAL_LIBS})
get_filename_component(_search_path "${_lib_filepath}" PATH)
if(_search_path)
list(APPEND _mitk_additional_library_search_paths "${_search_path}")
endif()
endforeach()
if(_mitk_additional_library_search_paths)
list(REMOVE_DUPLICATES _mitk_additional_library_search_paths)
set_property(GLOBAL PROPERTY MITK_ADDITIONAL_LIBRARY_SEARCH_PATHS ${_mitk_additional_library_search_paths})
endif()
endif()
# add the target name to a global property which is used in the top-level
# CMakeLists.txt file to export the target
set_property(GLOBAL APPEND PROPERTY MITK_MODULE_TARGETS ${MODULE_TARGET})
if(MODULE_AUTOLOAD_WITH)
# for auto-loaded modules, adapt the output directory
add_dependencies(${_module_autoload_meta_target} ${MODULE_TARGET})
if(WIN32)
set(_module_output_prop RUNTIME_OUTPUT_DIRECTORY)
else()
set(_module_output_prop LIBRARY_OUTPUT_DIRECTORY)
endif()
set(_module_output_dir ${CMAKE_${_module_output_prop}}/${MODULE_AUTOLOAD_WITH})
get_target_property(_module_is_imported ${MODULE_AUTOLOAD_WITH} IMPORTED)
if(NOT _module_is_imported)
# if the auto-loading module is not imported, get its location
# and put the auto-load module relative to it.
get_target_property(_module_output_dir ${MODULE_AUTOLOAD_WITH} ${_module_output_prop})
set_target_properties(${MODULE_TARGET} PROPERTIES
${_module_output_prop} ${_module_output_dir}/${MODULE_AUTOLOAD_WITH})
else()
set_target_properties(${MODULE_TARGET} PROPERTIES
${_module_output_prop} ${CMAKE_${_module_output_prop}}/${MODULE_AUTOLOAD_WITH})
endif()
set_target_properties(${MODULE_TARGET} PROPERTIES
MITK_AUTOLOAD_DIRECTORY ${MODULE_AUTOLOAD_WITH})
# add the auto-load module name as a property
set_property(TARGET ${MODULE_AUTOLOAD_WITH} APPEND PROPERTY MITK_AUTOLOAD_TARGETS ${MODULE_TARGET})
endif()
+
+ if(binary_res_files)
+ usFunctionAddResources(TARGET ${MODULE_TARGET}
+ SOURCE_OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${MODULE_TARGET}_binary_resources.cpp
+ WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/${res_dir}
+ FILES ${binary_res_files})
+ endif()
+ if(source_res_files)
+ usFunctionAddResources(TARGET ${MODULE_TARGET}
+ WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/${res_dir}
+ FILES ${source_res_files})
+ endif()
+
endif()
endif()
endif()
endif()
if(NOT MODULE_IS_ENABLED AND NOT MODULE_EXECUTABLE)
_MITK_CREATE_MODULE_CONF()
endif()
if(_MISSING_DEP)
if(MODULE_DESCRIPTION)
set(MODULE_DESCRIPTION "${MODULE_DESCRIPTION} (missing dependencies: ${_MISSING_DEP})")
else()
set(MODULE_DESCRIPTION "(missing dependencies: ${_MISSING_DEP})")
endif()
endif()
if(NOT MODULE_NO_FEATURE_INFO)
add_feature_info(${MODULE_NAME} MODULE_IS_ENABLED "${MODULE_DESCRIPTION}")
endif()
set(MODULE_NAME ${MODULE_NAME} PARENT_SCOPE)
set(MODULE_TARGET ${MODULE_TARGET} PARENT_SCOPE)
set(MODULE_IS_ENABLED ${MODULE_IS_ENABLED} PARENT_SCOPE)
set(MODULE_SUBPROJECTS ${MODULE_SUBPROJECTS} PARENT_SCOPE)
set(ALL_META_DEPENDENCIES ${ALL_META_DEPENDENCIES} PARENT_SCOPE)
endfunction()
diff --git a/CMake/mitkMacroCreateCTKPlugin.cmake b/CMake/mitkMacroCreateCTKPlugin.cmake
index b8c4ca5ff9..3067118d3a 100644
--- a/CMake/mitkMacroCreateCTKPlugin.cmake
+++ b/CMake/mitkMacroCreateCTKPlugin.cmake
@@ -1,87 +1,90 @@
macro(MACRO_CREATE_MITK_CTK_PLUGIN)
MACRO_PARSE_ARGUMENTS(_PLUGIN "EXPORT_DIRECTIVE;EXPORTED_INCLUDE_SUFFIXES;MODULE_DEPENDENCIES;MODULE_DEPENDS;PACKAGE_DEPENDS;SUBPROJECTS" "TEST_PLUGIN;NO_INSTALL" ${ARGN})
mitk_check_module_dependencies(MODULES MitkCore ${_PLUGIN_MODULE_DEPENDENCIES} ${_PLUGIN_MODULE_DEPENDS}
PACKAGES ${_PLUGIN_PACKAGE_DEPENDS}
MISSING_DEPENDENCIES_VAR _missing_deps
MODULE_DEPENDENCIES_VAR _module_deps
PACKAGE_DEPENDENCIES_VAR _package_deps)
if(_PLUGIN_MODULE_DEPENDENCIES)
message(WARNING "The MODULE_DEPENDENCIES argument is deprecated since 2014.03. Please use MODULE_DEPENDS instead.")
endif()
if(NOT _missing_deps)
if(_PLUGIN_TEST_PLUGIN)
set(is_test_plugin "TEST_PLUGIN")
set(_PLUGIN_NO_INSTALL 1)
else()
set(is_test_plugin)
endif()
if(_PLUGIN_NO_INSTALL)
set(plugin_no_install "NO_INSTALL")
else()
set(plugin_no_install)
endif()
_link_directories_for_packages(${_package_deps})
MACRO_CREATE_CTK_PLUGIN(EXPORT_DIRECTIVE ${_PLUGIN_EXPORT_DIRECTIVE}
EXPORTED_INCLUDE_SUFFIXES ${_PLUGIN_EXPORTED_INCLUDE_SUFFIXES}
DOXYGEN_TAGFILES ${_PLUGIN_DOXYGEN_TAGFILES}
MOC_OPTIONS -DBOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION -DBOOST_TT_HAS_OPERATOR_HPP_INCLUDED
${is_test_plugin} ${plugin_no_install})
mitk_use_modules(TARGET ${PLUGIN_TARGET}
MODULES MitkCore ${_PLUGIN_MODULE_DEPENDENCIES} ${_PLUGIN_MODULE_DEPENDS}
PACKAGES ${_PLUGIN_PACKAGE_DEPENDS}
)
+ set_property(TARGET ${PLUGIN_TARGET} APPEND PROPERTY COMPILE_DEFINITIONS US_MODULE_NAME=${PLUGIN_TARGET})
+ set_property(TARGET ${PLUGIN_TARGET} PROPERTY US_MODULE_NAME ${PLUGIN_TARGET})
+
if(ALL_META_DEPENDENCIES)
add_dependencies(${PLUGIN_TARGET} ${ALL_META_DEPENDENCIES})
endif()
if(MITK_DEFAULT_SUBPROJECTS AND NOT MY_SUBPROJECTS)
set(MY_SUBPROJECTS ${MITK_DEFAULT_SUBPROJECTS})
endif()
if(MY_SUBPROJECTS)
set_property(TARGET ${PLUGIN_TARGET} PROPERTY LABELS ${MY_SUBPROJECTS})
foreach(subproject ${MY_SUBPROJECTS})
add_dependencies(${subproject} ${PLUGIN_TARGET})
endforeach()
endif()
#------------------------------------------------------------#
#------------------ Installer support -----------------------#
if(NOT _PLUGIN_NO_INSTALL)
set(_autoload_targets )
foreach(_dependency ${_module_deps})
get_target_property(_dep_autoloads ${_dependency} MITK_AUTOLOAD_TARGETS)
if (_dep_autoloads)
list(APPEND _autoload_targets ${_dep_autoloads})
endif()
endforeach()
# The MITK_AUTOLOAD_TARGETS property is used in the mitkFunctionInstallAutoLoadModules
# macro which expects a list of plug-in targets.
if (_autoload_targets)
list(REMOVE_DUPLICATES _autoload_targets)
set_target_properties(${PLUGIN_TARGET} PROPERTIES MITK_AUTOLOAD_TARGETS "${_autoload_targets}")
endif()
endif()
else()
if(NOT MITK_BUILD_ALL_PLUGINS)
message(SEND_ERROR "${PROJECT_NAME} is missing requirements and won't be built. Missing: ${_missing_deps}")
else()
message(STATUS "${PROJECT_NAME} is missing requirements and won't be built. Missing: ${_missing_deps}")
endif()
endif()
endmacro()
diff --git a/CMake/mitkMacroCreateModuleTests.cmake b/CMake/mitkMacroCreateModuleTests.cmake
index 787d53862d..f61a702b39 100644
--- a/CMake/mitkMacroCreateModuleTests.cmake
+++ b/CMake/mitkMacroCreateModuleTests.cmake
@@ -1,147 +1,101 @@
#
# Create tests and testdriver for this module
#
# Usage: MITK_CREATE_MODULE_TESTS( [EXTRA_DRIVER_INIT init_code] )
#
# EXTRA_DRIVER_INIT is inserted as c++ code in the testdriver and will be executed before each test
#
macro(MITK_CREATE_MODULE_TESTS)
MACRO_PARSE_ARGUMENTS(MODULE_TEST
"EXTRA_DRIVER_INIT;EXTRA_DRIVER_INCLUDE;EXTRA_DEPENDS" "US_MODULE" ${ARGN})
if(BUILD_TESTING AND MODULE_IS_ENABLED)
- set(OLD_MOC_H_FILES ${MOC_H_FILES})
- set(MOC_H_FILES)
include(files.cmake)
include_directories(.)
- if(DEFINED MOC_H_FILES)
- QT4_WRAP_CPP(MODULE_TEST_GENERATED_MOC_CPP ${MOC_H_FILES} OPTIONS -DBOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
- endif(DEFINED MOC_H_FILES)
-
- mitk_check_module_dependencies(MODULES ${MODULE_NAME} MitkTestingHelper ${MODULE_TEST_EXTRA_DEPENDS}
- PACKAGE_DEPENDENCIES_VAR package_deps)
- _link_directories_for_packages(${package_deps})
-
set(TESTDRIVER ${MODULE_NAME}TestDriver)
- set(MODULE_TEST_EXTRA_DRIVER_INIT "${MODULE_TEST_EXTRA_DRIVER_INIT}")
-
- # Write a header file containing include directives and custom code
- # for the test driver.
- set(TESTDRIVER_EXTRA_INCLUDES )
- list(APPEND MODULE_TEST_EXTRA_DRIVER_INCLUDE "mitkLog.h")
- list(REMOVE_DUPLICATES MODULE_TEST_EXTRA_DRIVER_INCLUDE)
- foreach(_include ${MODULE_TEST_EXTRA_DRIVER_INCLUDE})
- set(TESTDRIVER_EXTRA_INCLUDES "${TESTDRIVER_EXTRA_INCLUDES}
-#include <${_include}>")
- endforeach()
- set(TESTDRIVER_EXTRA_INCLUDES "${TESTDRIVER_EXTRA_INCLUDES}
-#include
-std::vector globalCmdLineArgs;")
- set(_extra_include_file ${CMAKE_CURRENT_BINARY_DIR}/${TESTDRIVER}_extras.h)
- configure_file(${MITK_CMAKE_DIR}/mitkTestDriverExtraIncludes.h.in ${_extra_include_file})
- set(CMAKE_TESTDRIVER_BEFORE_TESTMAIN "
-for (int avIndex = 1; avIndex < ac; ++avIndex) globalCmdLineArgs.push_back(av[avIndex]);
-mitk::LoggingBackend::Register();
-${MODULE_TEST_EXTRA_DRIVER_INIT};"
-)
- set(CMAKE_TESTDRIVER_AFTER_TESTMAIN "mitk::LoggingBackend::Unregister();")
-
- create_test_sourcelist(MODULETEST_SOURCE ${MODULE_NAME}TestDriver.cpp
- ${MODULE_TESTS} ${MODULE_IMAGE_TESTS} ${MODULE_SURFACE_TESTS} ${MODULE_CUSTOM_TESTS}
- EXTRA_INCLUDE ${_extra_include_file}
- )
+ set(MODULE_TEST_EXTRA_DRIVER_INIT "${MODULE_TEST_EXTRA_DRIVER_INIT}")
+ set(_no_init NO_INIT)
if(MODULE_TEST_US_MODULE)
- set(testdriver_init_file )
- find_package(CppMicroServices QUIET NO_MODULE REQUIRED)
- # Create CppMicroServices initialization code
- usFunctionGenerateExecutableInit(testdriver_init_file
- IDENTIFIER ${TESTDRIVER}
- )
- list(APPEND TEST_CPP_FILES ${testdriver_init_file})
+ set(_no_init )
endif()
- add_executable(${TESTDRIVER} ${MODULETEST_SOURCE} ${MODULE_TEST_GENERATED_MOC_CPP} ${TEST_CPP_FILES})
- mitk_use_modules(TARGET ${TESTDRIVER}
- MODULES ${MODULE_NAME} MitkTestingHelper ${MODULE_TEST_EXTRA_DEPENDS}
- )
-
- if(MODULE_SUBPROJECTS)
- foreach(subproject ${MODULE_SUBPROJECTS})
- add_dependencies(${subproject} ${TESTDRIVER})
- endforeach()
- endif()
+ set(MITK_MODULE_NAME_REGEX_MATCH )
+ set(MITK_MODULE_NAME_REGEX_NOT_MATCH )
- # Add meta dependencies (e.g. on auto-load modules from depending modules)
- if(ALL_META_DEPENDENCIES)
- add_dependencies(${TESTDRIVER} ${ALL_META_DEPENDENCIES})
- endif()
+ set(_testdriver_file_list ${CMAKE_CURRENT_BINARY_DIR}/testdriver_files.cmake)
+ configure_file(${MITK_CMAKE_DIR}/mitkTestDriverFiles.cmake.in ${_testdriver_file_list} @ONLY)
+ mitk_create_executable(${TESTDRIVER}
+ DEPENDS ${MODULE_NAME} ${MODULE_TEST_EXTRA_DEPENDS} MitkTestingHelper
+ SUBPROJECTS ${MODULE_SUBPROJECTS}
+ FILES_CMAKE ${_testdriver_file_list}
+ NO_FEATURE_INFO NO_BATCH_FILE ${_no_init})
#
# Now tell CMake which tests should be run. This is done automatically
# for all tests in ${KITNAME}_TESTS and ${KITNAME}_IMAGE_TESTS. The IMAGE_TESTS
# are run for each image in the TESTIMAGES list.
#
+ include(files.cmake)
foreach( test ${MODULE_TESTS} )
get_filename_component(TName ${test} NAME_WE)
add_test(${TName} ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${TESTDRIVER} ${TName})
# Add labels for CDash subproject support
if(MODULE_SUBPROJECTS)
set_property(TEST ${TName} PROPERTY LABELS ${MODULE_SUBPROJECTS} MITK)
endif()
- endforeach( test )
+ endforeach()
foreach(image ${MODULE_TESTIMAGES} ${ADDITIONAL_TEST_IMAGES} )
if(EXISTS ${image})
set(IMAGE_FULL_PATH ${image})
- else(EXISTS ${image})
+ else()
# todo: maybe search other paths as well
# yes, please in mitk/Testing/Data, too
set(IMAGE_FULL_PATH ${MITK_DATA_DIR}/${image})
- endif(EXISTS ${image})
+ endif()
if(EXISTS ${IMAGE_FULL_PATH})
foreach( test ${MODULE_IMAGE_TESTS} )
get_filename_component(TName ${test} NAME_WE)
get_filename_component(ImageName ${IMAGE_FULL_PATH} NAME)
add_test(${TName}_${ImageName} ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${TESTDRIVER} ${TName} ${IMAGE_FULL_PATH})
# Add labels for CDash subproject support
if(MODULE_SUBPROJECTS)
set_property(TEST ${TName}_${ImageName} PROPERTY LABELS ${MODULE_SUBPROJECTS} MITK)
endif()
- endforeach( test )
- else(EXISTS ${IMAGE_FULL_PATH})
+ endforeach()
+ else()
message("!!!!! No such file: ${IMAGE_FULL_PATH} !!!!!")
- endif(EXISTS ${IMAGE_FULL_PATH})
- endforeach( image )
+ endif()
+ endforeach()
foreach(surface ${MODULE_TESTSURFACES} ${ADDITIONAL_TEST_SURFACES} )
if(EXISTS ${surface})
set(SURFACE_FULL_PATH ${surface})
- else(EXISTS ${surface})
+ else()
# todo: maybe search other paths as well
# yes, please in mitk/Testing/Data, too
set(SURFACE_FULL_PATH ${MITK_DATA_DIR}/${surface})
- endif(EXISTS ${surface})
+ endif()
if(EXISTS ${SURFACE_FULL_PATH})
foreach( test ${MODULE_SURFACE_TESTS} )
get_filename_component(TName ${test} NAME_WE)
get_filename_component(SurfaceName ${SURFACE_FULL_PATH} NAME)
add_test(${TName}_${SurfaceName} ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${TESTDRIVER} ${TName} ${SURFACE_FULL_PATH})
# Add labels for CDash subproject support
if(MODULE_SUBPROJECTS)
set_property(TEST ${TName}_${SurfaceName} PROPERTY LABELS ${MODULE_SUBPROJECTS} MITK)
endif()
- endforeach( test )
- else(EXISTS ${SURFACE_FULL_PATH})
+ endforeach()
+ else()
message("!!!!! No such surface file: ${SURFACE_FULL_PATH} !!!!!")
- endif(EXISTS ${SURFACE_FULL_PATH})
- endforeach( surface )
+ endif()
+ endforeach()
- set(MOC_H_FILES ${OLD_MOC_H_FILES})
- endif(BUILD_TESTING AND MODULE_IS_ENABLED)
+ endif()
-endmacro(MITK_CREATE_MODULE_TESTS)
+endmacro()
diff --git a/CMake/mitkTestDriverFiles.cmake.in b/CMake/mitkTestDriverFiles.cmake.in
new file mode 100644
index 0000000000..d1154ef6ad
--- /dev/null
+++ b/CMake/mitkTestDriverFiles.cmake.in
@@ -0,0 +1,47 @@
+if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/files.cmake)
+ include(${CMAKE_CURRENT_SOURCE_DIR}/files.cmake)
+endif()
+
+# Write a header file containing include directives and custom code
+# for the test driver.
+set(TESTDRIVER_EXTRA_INCLUDES )
+list(APPEND MODULE_TEST_EXTRA_DRIVER_INCLUDE "mitkLog.h")
+list(REMOVE_DUPLICATES MODULE_TEST_EXTRA_DRIVER_INCLUDE)
+
+foreach(_include ${MODULE_TEST_EXTRA_DRIVER_INCLUDE})
+ set(TESTDRIVER_EXTRA_INCLUDES "${TESTDRIVER_EXTRA_INCLUDES}
+#include <${_include}>")
+endforeach()
+
+set(TESTDRIVER_EXTRA_INCLUDES "${TESTDRIVER_EXTRA_INCLUDES}
+#include
+std::vector globalCmdLineArgs;")
+
+set(_extra_include_file ${CMAKE_CURRENT_BINARY_DIR}/${TESTDRIVER}_extras.h)
+configure_file(${MITK_CMAKE_DIR}/mitkTestDriverExtraIncludes.h.in ${_extra_include_file})
+
+set(CMAKE_TESTDRIVER_BEFORE_TESTMAIN "
+for (int avIndex = 1; avIndex < ac; ++avIndex) globalCmdLineArgs.push_back(av[avIndex]);
+mitk::LoggingBackend::Register();
+${MODULE_TEST_EXTRA_DRIVER_INIT};"
+)
+
+set(CMAKE_TESTDRIVER_AFTER_TESTMAIN "mitk::LoggingBackend::Unregister();")
+
+create_test_sourcelist(_test_cpp_files ${MODULE_NAME}_main.cpp
+ ${MODULE_TESTS} ${MODULE_IMAGE_TESTS} ${MODULE_SURFACE_TESTS} ${MODULE_CUSTOM_TESTS}
+ EXTRA_INCLUDE ${_extra_include_file}
+)
+list(APPEND CPP_FILES ${_test_cpp_files})
+
+# Some old CMake scripts use TEST_CPP_FILES in their files.cmake
+# file of the test driver to add source fiels to the executable
+# (they should just use CPP_FILES like in any other files.cmake
+# file instead).
+if(TEST_CPP_FILES)
+ list(APPEND CPP_FILES ${TEST_CPP_FILES})
+endif()
+
+if(MODULE_RESOURCE_FILES)
+ list(APPEND RESOURCE_FILES ${MODULE_RESOURCE_FILES})
+endif()
\ No newline at end of file
diff --git a/CMakeExternals/Boost.cmake b/CMakeExternals/Boost.cmake
index 472d69ca3d..6b609f1d7d 100644
--- a/CMakeExternals/Boost.cmake
+++ b/CMakeExternals/Boost.cmake
@@ -1,109 +1,109 @@
#-----------------------------------------------------------------------------
# Boost
#-----------------------------------------------------------------------------
if(MITK_USE_Boost)
# Sanity checks
if(DEFINED BOOST_ROOT AND NOT EXISTS ${BOOST_ROOT})
message(FATAL_ERROR "BOOST_ROOT variable is defined but corresponds to non-existing directory")
endif()
string(REPLACE "^^" ";" MITK_USE_Boost_LIBRARIES "${MITK_USE_Boost_LIBRARIES}")
set(proj Boost)
set(proj_DEPENDENCIES )
set(Boost_DEPENDS ${proj})
if(NOT DEFINED BOOST_ROOT AND NOT MITK_USE_SYSTEM_Boost)
set(_boost_libs )
set(INSTALL_COMMAND "")
if(MITK_USE_Boost_LIBRARIES)
# Set the boost root to the libraries install directory
set(BOOST_ROOT "${CMAKE_CURRENT_BINARY_DIR}/${proj}-install")
# We need binary boost libraries
foreach(_boost_lib ${MITK_USE_Boost_LIBRARIES})
set(_boost_libs ${_boost_libs} --with-${_boost_lib})
endforeach()
if(WIN32)
set(_boost_variant "")
set(_shell_extension .bat)
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
set(_boost_address_model "address-model=64")
else()
set(_boost_address_model "address-model=32")
endif()
if(MSVC)
if(MSVC_VERSION EQUAL 1400)
set(_boost_toolset "toolset=msvc-8.0")
elseif(MSVC_VERSION EQUAL 1500)
set(_boost_toolset "toolset=msvc-9.0")
elseif(MSVC_VERSION EQUAL 1600)
set(_boost_toolset "toolset=msvc-10.0")
elseif(MSVC_VERSION EQUAL 1700)
set(_boost_toolset "toolset=msvc-11.0")
endif()
endif()
else()
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
set(_boost_variant "variant=debug")
else()
set(_boost_variant "variant=release")
endif()
set(_shell_extension .sh)
endif()
if(APPLE)
set(APPLE_CMAKE_SCRIPT ${CMAKE_CURRENT_BINARY_DIR}/${proj}-cmake/ChangeBoostLibsInstallNameForMac.cmake)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/CMakeExternals/ChangeBoostLibsInstallNameForMac.cmake.in ${APPLE_CMAKE_SCRIPT} @ONLY)
set(INSTALL_COMMAND ${CMAKE_COMMAND} -P ${APPLE_CMAKE_SCRIPT})
# Set OSX_SYSROOT
set (APPLE_SYSROOT_FLAG)
if (NOT ${CMAKE_OSX_SYSROOT} STREQUAL "")
set (APPLE_SYSROOT_FLAG --sysroot=${CMAKE_OSX_SYSROOT})
endif()
# Set the boost build command for apple
set(_boost_build_cmd ${CMAKE_CURRENT_BINARY_DIR}/${proj}-src/bjam ${APPLE_SYSROOT_FLAG} --builddir=${CMAKE_CURRENT_BINARY_DIR}/${proj}-build --prefix=${CMAKE_CURRENT_BINARY_DIR}/${proj}-install
${_boost_toolset} ${_boost_address_model} ${_boost_variant} ${_boost_libs} link=shared,static threading=multi runtime-link=shared -q install)
else()
set(_boost_build_cmd ${CMAKE_CURRENT_BINARY_DIR}/${proj}-src/bjam --build-dir=${CMAKE_CURRENT_BINARY_DIR}/${proj}-build --prefix=${CMAKE_CURRENT_BINARY_DIR}/${proj}-install ${_boost_toolset} ${_boost_address_model}
${_boost_variant} ${_boost_libs} link=shared,static threading=multi runtime-link=shared -q install)
endif()
set(_boost_cfg_cmd ${CMAKE_CURRENT_BINARY_DIR}/${proj}-src/bootstrap${_shell_extension})
else()
# If no libraries are specified set the boost root to the boost src directory
set(BOOST_ROOT "${CMAKE_CURRENT_BINARY_DIR}/${proj}-src")
set(_boost_cfg_cmd )
set(_boost_build_cmd )
endif()
ExternalProject_Add(${proj}
SOURCE_DIR ${CMAKE_BINARY_DIR}/${proj}-src
# Boost needs in-source builds
BINARY_DIR ${proj}-src
PREFIX ${proj}-cmake
- URL ${MITK_THIRDPARTY_DOWNLOAD_PREFIX_URL}/boost_1_55_0.tar.bz2
- URL_MD5 d6eef4b4cacb2183f2bf265a5a03a354
+ URL ${MITK_THIRDPARTY_DOWNLOAD_PREFIX_URL}/boost_1_56_0.tar.bz2
+ URL_MD5 a744cf167b05d72335f27c88115f211d
INSTALL_DIR ${proj}-install
CONFIGURE_COMMAND "${_boost_cfg_cmd}"
BUILD_COMMAND "${_boost_build_cmd}"
INSTALL_COMMAND "${INSTALL_COMMAND}"
DEPENDS ${proj_DEPENDENCIES}
)
else()
mitkMacroEmptyExternalProject(${proj} "${proj_DEPENDENCIES}")
endif()
endif()
diff --git a/CMakeExternals/Eigen.cmake b/CMakeExternals/Eigen.cmake
new file mode 100644
index 0000000000..6f50d23e0f
--- /dev/null
+++ b/CMakeExternals/Eigen.cmake
@@ -0,0 +1,31 @@
+#-----------------------------------------------------------------------------
+# Eigen
+#-----------------------------------------------------------------------------
+
+# Sanity checks
+if(DEFINED Eigen_DIR AND NOT EXISTS ${Eigen_DIR})
+ message(FATAL_ERROR "Eigen_DIR variable is defined but corresponds to non-existing directory")
+endif()
+
+set(proj Eigen)
+set(proj_DEPENDENCIES )
+set(Eigen_DEPENDS ${proj})
+
+if(NOT DEFINED Eigen_DIR)
+
+ ExternalProject_Add(${proj}
+ SOURCE_DIR ${CMAKE_BINARY_DIR}/${proj}-src
+ BINARY_DIR ${proj}-cmake
+ URL ${MITK_THIRDPARTY_DOWNLOAD_PREFIX_URL}/Eigen-3.2.2.tar.gz
+ URL_MD5 2809c6a623ef48e7ab3d6a2630b94a29
+ CMAKE_ARGS
+ -DCMAKE_INSTALL_PREFIX:PATH=${CMAKE_CURRENT_BINARY_DIR}/${proj}-install
+ )
+
+ set(Eigen_DIR ${CMAKE_CURRENT_BINARY_DIR}/${proj}-install)
+
+else()
+
+ mitkMacroEmptyExternalProject(${proj} "${proj_DEPENDENCIES}")
+
+endif()
diff --git a/CMakeExternals/MITKData.cmake b/CMakeExternals/MITKData.cmake
index e764edaba2..0eb4565c94 100644
--- a/CMakeExternals/MITKData.cmake
+++ b/CMakeExternals/MITKData.cmake
@@ -1,36 +1,36 @@
#-----------------------------------------------------------------------------
# MITK Data
#-----------------------------------------------------------------------------
# Sanity checks
if(DEFINED MITK_DATA_DIR AND NOT EXISTS ${MITK_DATA_DIR})
message(FATAL_ERROR "MITK_DATA_DIR variable is defined but corresponds to non-existing directory")
endif()
set(proj MITK-Data)
set(proj_DEPENDENCIES)
set(MITK-Data_DEPENDS ${proj})
if(BUILD_TESTING)
- set(revision_tag acedec01)
+ set(revision_tag d96c6dab)
# ^^^^^^^^ these are just to check correct length of hash part
ExternalProject_Add(${proj}
URL ${MITK_THIRDPARTY_DOWNLOAD_PREFIX_URL}/MITK-Data_${revision_tag}.tar.gz
UPDATE_COMMAND ""
CONFIGURE_COMMAND ""
BUILD_COMMAND ""
INSTALL_COMMAND ""
DEPENDS ${proj_DEPENDENCIES}
)
set(MITK_DATA_DIR ${ep_source_dir}/${proj})
else()
mitkMacroEmptyExternalProject(${proj} "${proj_DEPENDENCIES}")
endif(BUILD_TESTING)
diff --git a/CMakeExternals/PatchVTK.cmake b/CMakeExternals/PatchVTK.cmake
new file mode 100644
index 0000000000..4eb6989741
--- /dev/null
+++ b/CMakeExternals/PatchVTK.cmake
@@ -0,0 +1,5 @@
+set(path "Rendering/OpenGL/vtkXOpenGLRenderWindow.cxx")
+file(STRINGS ${path} contents NEWLINE_CONSUME)
+string(REPLACE "//#define GLX_GLXEXT_LEGACY" "#define GLX_GLXEXT_LEGACY" contents ${contents})
+set(CONTENTS ${contents})
+configure_file(${TEMPLATE_FILE} ${path} @ONLY)
diff --git a/CMakeExternals/SOFA.cmake b/CMakeExternals/SOFA.cmake
index ea2caaa3ca..78974ecf1a 100644
--- a/CMakeExternals/SOFA.cmake
+++ b/CMakeExternals/SOFA.cmake
@@ -1,100 +1,100 @@
#-----------------------------------------------------------------------------
# SOFA
#-----------------------------------------------------------------------------
if(MITK_USE_SOFA)
# Sanity checks
if(DEFINED SOFA_DIR AND NOT EXISTS ${SOFA_DIR})
message(FATAL_ERROR "SOFA_DIR variable is defined but corresponds to non-existing directory")
endif()
set(proj SOFA)
set(proj_DEPENDENCIES Boost GLEW)
set(SOFA_DEPENDS ${proj})
set(preconfigure_cmake_args
-DGLEW_DIR:PATH=${GLEW_DIR}
-DSOFA-APPLICATION_MODELER:BOOL=OFF
-DSOFA-APPLICATION_RUNSOFA:BOOL=OFF
-DSOFA-APPLICATION_SOFABATCH:BOOL=OFF
-DSOFA-EXTERNAL_BOOST:BOOL=ON
-DSOFA-EXTERNAL_BOOST_PATH:PATH=${CMAKE_BINARY_DIR}/Boost-install/lib
-DSOFA-EXTERNAL_CSPARSE:BOOL=ON
-DSOFA-EXTERNAL_GLEW:BOOL=ON
-DSOFA-EXTERNAL_PNG:BOOL=OFF
-DSOFA-EXTERNAL_ZLIB:BOOL=OFF
-DSOFA-LIB_COMPONENT_SPARSE_SOLVER:BOOL=ON
-DSOFA-LIB_GUI_GLUT:BOOL=OFF
-DSOFA-LIB_GUI_QT:BOOL=OFF
-DSOFA-LIB_GUI_QTVIEWER:BOOL=OFF
-DSOFA-TUTORIAL_CHAIN_HYBRID:BOOL=OFF
-DSOFA-TUTORIAL_COMPOSITE_OBJECT:BOOL=OFF
-DSOFA-TUTORIAL_MIXED_PENDULUM:BOOL=OFF
-DSOFA-TUTORIAL_ONE_PARTICLE:BOOL=OFF
-DSOFA-TUTORIAL_ONE_TETRAHEDRON:BOOL=OFF
)
if(NOT APPLE)
list(APPEND proj_DEPENDENCIES GLUT)
list(APPEND preconfigure_cmake_args
-DSOFA-EXTERNAL_FREEGLUT:BOOL=ON
-DGLUT_DIR:PATH=${GLUT_DIR}
)
endif()
if(NOT MITK_USE_SYSTEM_Boost)
list(APPEND preconfigure_cmake_args
-DBoost_NO_SYSTEM_PATHS:BOOL=ON
-DBOOST_INCLUDEDIR:PATH=${CMAKE_BINARY_DIR}/Boost-install/include
-DBOOST_LIBRARYDIR:PATH=${CMAKE_BINARY_DIR}/Boost-install/lib
- -DBoost_ADDITIONAL_VERSIONS:STRING=1.55
+ -DBoost_ADDITIONAL_VERSIONS:STRING=1.56
)
endif()
if(MITK_USE_SOFA_PLUGINS_DIR)
list(APPEND preconfigure_cmake_args
-DSOFA_APPLICATIONS_PLUGINS_DIR:PATH=${MITK_USE_SOFA_PLUGINS_DIR}
)
foreach(plugin ${MITK_USE_SOFA_PLUGINS})
string(TOUPPER ${plugin} plugin)
list(APPEND preconfigure_cmake_args
-DSOFA-PLUGIN_${plugin}:BOOL=ON
)
endforeach()
endif()
set(rev "10669")
set(SOFA_PATCH_COMMAND ${CMAKE_COMMAND} -DTEMPLATE_FILE:FILEPATH=${MITK_SOURCE_DIR}/CMakeExternals/EmptyFileForPatching.dummy -P ${MITK_SOURCE_DIR}/CMakeExternals/PatchSOFA-rev${rev}.cmake)
set(SOFA_PRECONFIGURE_COMMAND ${CMAKE_COMMAND} -G${gen} ${ep_common_args} ${preconfigure_cmake_args} ${boost_cmake_args} ${CMAKE_BINARY_DIR}/${proj}-src)
if(NOT DEFINED SOFA_DIR)
ExternalProject_Add(${proj}
SOURCE_DIR ${CMAKE_BINARY_DIR}/${proj}-src
BINARY_DIR ${proj}-build
PREFIX ${proj}-cmake
URL ${MITK_THIRDPARTY_DOWNLOAD_PREFIX_URL}/SOFA-rev${rev}.tar.gz
URL_MD5 d01a194f54b933f4cdfdfc75b2f81a2f
PATCH_COMMAND ${SOFA_PATCH_COMMAND}
INSTALL_COMMAND ""
CMAKE_GENERATOR ${gen}
CMAKE_ARGS
${ep_common_args}
DEPENDS ${proj_DEPENDENCIES}
)
ExternalProject_Add_Step(${proj} preconfigure
COMMAND ${SOFA_PRECONFIGURE_COMMAND}
WORKING_DIRECTORY ${proj}-build
DEPENDEES patch
DEPENDERS configure
LOG 1
)
set(SOFA_DIR ${CMAKE_CURRENT_BINARY_DIR}/${proj}-build)
else()
mitkMacroEmptyExternalProject(${proj} "${proj_DEPENDENCIES}")
endif()
endif()
diff --git a/CMakeExternals/VTK.cmake b/CMakeExternals/VTK.cmake
index 9679cdefd5..cd2ae6a8d9 100644
--- a/CMakeExternals/VTK.cmake
+++ b/CMakeExternals/VTK.cmake
@@ -1,111 +1,114 @@
#-----------------------------------------------------------------------------
# VTK
#-----------------------------------------------------------------------------
if(WIN32)
option(VTK_USE_SYSTEM_FREETYPE OFF)
else(WIN32)
option(VTK_USE_SYSTEM_FREETYPE ON)
endif(WIN32)
# Sanity checks
if(DEFINED VTK_DIR AND NOT EXISTS ${VTK_DIR})
message(FATAL_ERROR "VTK_DIR variable is defined but corresponds to non-existing directory")
endif()
set(proj VTK)
set(proj_DEPENDENCIES )
set(VTK_DEPENDS ${proj})
+ set(VTK_PATCH_COMMAND ${CMAKE_COMMAND} -DTEMPLATE_FILE:FILEPATH=${MITK_SOURCE_DIR}/CMakeExternals/EmptyFileForPatching.dummy -P ${MITK_SOURCE_DIR}/CMakeExternals/PatchVTK.cmake)
+
if(NOT DEFINED VTK_DIR)
set(additional_cmake_args )
if(MINGW)
set(additional_cmake_args
-DCMAKE_USE_WIN32_THREADS:BOOL=ON
-DCMAKE_USE_PTHREADS:BOOL=OFF
-DVTK_USE_VIDEO4WINDOWS:BOOL=OFF # no header files provided by MinGW
)
endif()
if(WIN32)
# see http://bugs.mitk.org/show_bug.cgi?id=17858
list(APPEND additional_cmake_args
-DVTK_DO_NOT_DEFINE_OSTREAM_SLL:BOOL=ON
-DVTK_DO_NOT_DEFINE_OSTREAM_ULL:BOOL=ON
)
endif()
# Optionally enable memory leak checks for any objects derived from vtkObject. This
# will force unit tests to fail if they have any of these memory leaks.
option(MITK_VTK_DEBUG_LEAKS OFF)
mark_as_advanced(MITK_VTK_DEBUG_LEAKS)
list(APPEND additional_cmake_args
-DVTK_DEBUG_LEAKS:BOOL=${MITK_VTK_DEBUG_LEAKS}
)
if(MITK_USE_Python)
if(NOT MITK_USE_SYSTEM_PYTHON)
list(APPEND proj_DEPENDENCIES Python)
endif()
list(APPEND additional_cmake_args
-DVTK_WRAP_PYTHON:BOOL=ON
-DVTK_USE_TK:BOOL=OFF
-DVTK_WINDOWS_PYTHON_DEBUGGABLE:BOOL=OFF
-DPYTHON_EXECUTABLE:FILEPATH=${PYTHON_EXECUTABLE}
-DPYTHON_INCLUDE_DIR:PATH=${PYTHON_INCLUDE_DIR}
-DPYTHON_INCLUDE_DIR2:PATH=${PYTHON_INCLUDE_DIR2}
-DPYTHON_LIBRARY:FILEPATH=${PYTHON_LIBRARY}
)
else()
list(APPEND additional_cmake_args
-DVTK_WRAP_PYTHON:BOOL=OFF
-DVTK_WINDOWS_PYTHON_DEBUGGABLE:BOOL=OFF
)
endif()
if(MITK_USE_QT)
list(APPEND additional_cmake_args
-DVTK_QT_VERSION:STRING=${DESIRED_QT_VERSION}
-DQT_QMAKE_EXECUTABLE:FILEPATH=${QT_QMAKE_EXECUTABLE}
-DModule_vtkGUISupportQt:BOOL=ON
-DModule_vtkGUISupportQtWebkit:BOOL=ON
-DModule_vtkGUISupportQtSQL:BOOL=ON
-DModule_vtkRenderingQt:BOOL=ON
-DVTK_Group_Qt:BOOL=ON
)
endif()
set(VTK_URL ${MITK_THIRDPARTY_DOWNLOAD_PREFIX_URL}/VTK-6.1.0+74f4888.tar.gz)
set(VTK_URL_MD5 1f19dae22c42c032109bd3cf91c4e8c9)
ExternalProject_Add(${proj}
SOURCE_DIR ${CMAKE_BINARY_DIR}/${proj}-src
BINARY_DIR ${proj}-build
PREFIX ${proj}-cmake
URL ${VTK_URL}
URL_MD5 ${VTK_URL_MD5}
+ PATCH_COMMAND ${VTK_PATCH_COMMAND}
INSTALL_COMMAND ""
CMAKE_GENERATOR ${gen}
CMAKE_ARGS
${ep_common_args}
-DVTK_WRAP_TCL:BOOL=OFF
-DVTK_WRAP_PYTHON:BOOL=OFF
-DVTK_WRAP_JAVA:BOOL=OFF
-DBUILD_SHARED_LIBS:BOOL=ON
-DVTK_USE_SYSTEM_FREETYPE:BOOL=${VTK_USE_SYSTEM_FREETYPE}
-DVTK_LEGACY_REMOVE:BOOL=ON
-DModule_vtkTestingRendering:BOOL=ON
-DVTK_MAKE_INSTANTIATORS:BOOL=ON
${additional_cmake_args}
DEPENDS ${proj_DEPENDENCIES}
)
set(VTK_DIR ${CMAKE_CURRENT_BINARY_DIR}/${proj}-build)
else()
mitkMacroEmptyExternalProject(${proj} "${proj_DEPENDENCIES}")
endif()
diff --git a/CMakeLists.txt b/CMakeLists.txt
index b9ea62a4ef..88f90f7cdc 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,1073 +1,1077 @@
set(DESIRED_QT_VERSION 4 CACHE STRING "Pick a version of Qt to use: 4 or 5")
-if(DESIRED_QT_VERSION MATCHES "4")
+
+if (${CMAKE_GENERATOR} MATCHES "^Visual Studio 12.*$")
+ message("For MS Visual Studio 12 (2013) the minimum required CMake version is 3")
+ cmake_minimum_required(VERSION 3.0)
+elseif(DESIRED_QT_VERSION MATCHES "4")
cmake_minimum_required(VERSION 2.8.9)
else()
cmake_minimum_required(VERSION 2.8.12)
endif()
#-----------------------------------------------------------------------------
# Include ctest launchers for dashboard in case of makefile generator
#-----------------------------------------------------------------------------
if(${CMAKE_VERSION} VERSION_GREATER "2.8.9")
include(CTestUseLaunchers)
endif()
#-----------------------------------------------------------------------------
# Set a default build type if none was specified
#-----------------------------------------------------------------------------
if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
message(STATUS "Setting build type to 'Debug' as none was specified.")
set(CMAKE_BUILD_TYPE Debug CACHE STRING "Choose the type of build." FORCE)
# Set the possible values of build type for cmake-gui
set_property(CACHE CMAKE_BUILD_TYPE PROPERTY
STRINGS "Debug" "Release" "MinSizeRel" "RelWithDebInfo")
endif()
#-----------------------------------------------------------------------------
# Superbuild Option - Enabled by default
#-----------------------------------------------------------------------------
option(MITK_USE_SUPERBUILD "Build MITK and the projects it depends on via SuperBuild.cmake." ON)
if(MITK_USE_SUPERBUILD)
project(MITK-superbuild)
set(MITK_SOURCE_DIR ${PROJECT_SOURCE_DIR})
set(MITK_BINARY_DIR ${PROJECT_BINARY_DIR})
else()
project(MITK)
endif()
#-----------------------------------------------------------------------------
# Warn if source or build path is too long
#-----------------------------------------------------------------------------
if(WIN32)
set(_src_dir_length_max 50)
set(_bin_dir_length_max 50)
if(MITK_USE_SUPERBUILD)
set(_src_dir_length_max 43) # _src_dir_length_max - strlen(ITK-src)
set(_bin_dir_length_max 40) # _bin_dir_length_max - strlen(MITK-build)
endif()
string(LENGTH "${MITK_SOURCE_DIR}" _src_n)
string(LENGTH "${MITK_BINARY_DIR}" _bin_n)
# The warnings should be converted to errors
if(_src_n GREATER _src_dir_length_max)
message(WARNING "MITK source code directory path length is too long (${_src_n} > ${_src_dir_length_max})."
"Please move the MITK source code directory to a directory with a shorter path." )
endif()
if(_bin_n GREATER _bin_dir_length_max)
message(WARNING "MITK build directory path length is too long (${_bin_n} > ${_bin_dir_length_max})."
"Please move the MITK build directory to a directory with a shorter path." )
endif()
endif()
#-----------------------------------------------------------------------------
# See http://cmake.org/cmake/help/cmake-2-8-docs.html#section_Policies for details
#-----------------------------------------------------------------------------
set(project_policies
CMP0001 # NEW: CMAKE_BACKWARDS_COMPATIBILITY should no longer be used.
CMP0002 # NEW: Logical target names must be globally unique.
CMP0003 # NEW: Libraries linked via full path no longer produce linker search paths.
CMP0004 # NEW: Libraries linked may NOT have leading or trailing whitespace.
CMP0005 # NEW: Preprocessor definition values are now escaped automatically.
CMP0006 # NEW: Installing MACOSX_BUNDLE targets requires a BUNDLE DESTINATION.
CMP0007 # NEW: List command no longer ignores empty elements.
CMP0008 # NEW: Libraries linked by full-path must have a valid library file name.
CMP0009 # NEW: FILE GLOB_RECURSE calls should not follow symlinks by default.
CMP0010 # NEW: Bad variable reference syntax is an error.
CMP0011 # NEW: Included scripts do automatic cmake_policy PUSH and POP.
CMP0012 # NEW: if() recognizes numbers and boolean constants.
CMP0013 # NEW: Duplicate binary directories are not allowed.
CMP0014 # NEW: Input directories must have CMakeLists.txt
CMP0020 # NEW: Automatically link Qt executables to qtmain target on Windows
)
foreach(policy ${project_policies})
if(POLICY ${policy})
cmake_policy(SET ${policy} NEW)
endif()
endforeach()
#-----------------------------------------------------------------------------
# Update CMake module path
#------------------------------------------------------------------------------
set(MITK_CMAKE_DIR ${MITK_SOURCE_DIR}/CMake)
set(CMAKE_MODULE_PATH
${MITK_CMAKE_DIR}
${CMAKE_MODULE_PATH}
)
#-----------------------------------------------------------------------------
# CMake function(s) and macro(s)
#-----------------------------------------------------------------------------
include(mitkMacroEmptyExternalProject)
include(mitkFunctionGenerateProjectXml)
include(mitkFunctionSuppressWarnings)
include(mitkFunctionEnableBuildConfiguration)
include(FeatureSummary)
SUPPRESS_VC_DEPRECATED_WARNINGS()
#-----------------------------------------------------------------------------
# Output directories.
#-----------------------------------------------------------------------------
foreach(type LIBRARY RUNTIME ARCHIVE)
# Make sure the directory exists
if(DEFINED MITK_CMAKE_${type}_OUTPUT_DIRECTORY
AND NOT EXISTS ${MITK_CMAKE_${type}_OUTPUT_DIRECTORY})
message("Creating directory MITK_CMAKE_${type}_OUTPUT_DIRECTORY: ${MITK_CMAKE_${type}_OUTPUT_DIRECTORY}")
file(MAKE_DIRECTORY "${MITK_CMAKE_${type}_OUTPUT_DIRECTORY}")
endif()
if(MITK_USE_SUPERBUILD)
set(output_dir ${MITK_BINARY_DIR}/bin)
if(NOT DEFINED MITK_CMAKE_${type}_OUTPUT_DIRECTORY)
set(MITK_CMAKE_${type}_OUTPUT_DIRECTORY ${MITK_BINARY_DIR}/MITK-build/bin)
endif()
else()
if(NOT DEFINED MITK_CMAKE_${type}_OUTPUT_DIRECTORY)
set(output_dir ${MITK_BINARY_DIR}/bin)
else()
set(output_dir ${MITK_CMAKE_${type}_OUTPUT_DIRECTORY})
endif()
endif()
set(CMAKE_${type}_OUTPUT_DIRECTORY ${output_dir} CACHE INTERNAL "Single output directory for building all libraries.")
mark_as_advanced(CMAKE_${type}_OUTPUT_DIRECTORY)
endforeach()
#-----------------------------------------------------------------------------
# Additional MITK Options (also shown during superbuild)
#-----------------------------------------------------------------------------
option(BUILD_SHARED_LIBS "Build MITK with shared libraries" ON)
option(WITH_COVERAGE "Enable/Disable coverage" OFF)
option(BUILD_TESTING "Test the project" ON)
macro(env_option name doc value)
set(_value $ENV{${name}})
if("${_value}" STREQUAL "")
set(_value ${value})
endif()
option(${name} "${doc}" ${_value})
endmacro()
# -----------------------------------------
# Qt version related variables
env_option(MITK_USE_QT "Use Nokia's Qt library" ON)
set(MITK_DESIRED_QT_VERSION ${DESIRED_QT_VERSION})
if(MITK_USE_QT)
# find the package at the very beginning, so that QT4_FOUND is available
if(DESIRED_QT_VERSION MATCHES 4)
set(MITK_QT4_MINIMUM_VERSION 4.7)
find_package(Qt4 ${MITK_QT4_MINIMUM_VERSION} REQUIRED)
set(MITK_USE_Qt4 TRUE)
set(MITK_USE_Qt5 FALSE)
endif()
if(DESIRED_QT_VERSION MATCHES 5)
set(MITK_QT5_MINIMUM_VERSION 5.0.0)
set(MITK_USE_Qt4 FALSE)
set(MITK_USE_Qt5 TRUE)
set(QT5_INSTALL_PREFIX "" CACHE PATH "The install location of Qt5")
set(CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH} ${QT5_INSTALL_PREFIX})
find_package(Qt5Core ${MITK_QT5_MINIMUM_VERSION} REQUIRED)
find_package(Qt5Widgets ${MITK_QT5_MINIMUM_VERSION} REQUIRED)
endif()
else()
set(MITK_USE_Qt4 FALSE)
set(MITK_USE_Qt5 FALSE)
endif()
# -----------------------------------------
# MITK_USE_* build variables
env_option(MITK_BUILD_ALL_APPS "Build all MITK applications" OFF)
set(MITK_BUILD_TUTORIAL OFF CACHE INTERNAL "Deprecated! Use MITK_BUILD_EXAMPLES instead!")
env_option(MITK_BUILD_EXAMPLES "Build the MITK Examples" ${MITK_BUILD_TUTORIAL})
env_option(MITK_USE_ACVD "Use Approximated Centroidal Voronoi Diagrams" OFF)
env_option(MITK_USE_CppUnit "Use CppUnit for unit tests" ON)
if(BUILD_TESTING AND NOT MITK_USE_CppUnit)
message("> Forcing MITK_USE_CppUnit to ON because BUILD_TESTING=ON")
set(MITK_USE_CppUnit ON CACHE BOOL "Use CppUnit for unit tests" FORCE)
endif()
env_option(MITK_USE_GLEW "Use the GLEW library" ON)
env_option(MITK_USE_Boost "Use the Boost C++ library" OFF)
env_option(MITK_USE_BLUEBERRY "Build the BlueBerry platform" ON)
env_option(MITK_USE_CTK "Use CTK in MITK" ON)
env_option(MITK_USE_DCMTK "EXPERIMENTAL, superbuild only: Use DCMTK in MITK" ${MITK_USE_CTK})
env_option(MITK_USE_OpenCV "Use Intel's OpenCV library" OFF)
env_option(MITK_USE_OpenCL "Use OpenCL GPU-Computing library" OFF)
env_option(MITK_USE_Poco "Use the Poco library" ON)
env_option(MITK_USE_SOFA "Use Simulation Open Framework Architecture" OFF)
env_option(MITK_USE_Python "Use Python wrapping in MITK" OFF)
env_option(MITK_USE_SimpleITK "Use the SimpleITK library" OFF)
set(MITK_USE_CableSwig ${MITK_USE_Python})
option(MITK_ENABLE_PIC_READER "Enable support for reading the DKFZ pic file format." ON)
set(MITK_BUILD_CONFIGURATION "Custom" CACHE STRING "Use pre-defined MITK configurations")
set_property(CACHE MITK_BUILD_CONFIGURATION PROPERTY STRINGS Custom Default All)
mitkFunctionEnableBuildConfiguration()
mark_as_advanced(MITK_BUILD_ALL_APPS
MITK_USE_CppUnit
MITK_USE_GLEW
MITK_USE_CTK
MITK_USE_DCMTK
MITK_ENABLE_PIC_READER
MITK_BUILD_CONFIGURATION
)
if(MITK_USE_Python)
if(APPLE)
message(WARNING "Python wrapping is unsuported on mac OSX!")
set(MITK_USE_Python OFF CACHE BOOL "Use Python wrapping in MITK" FORCE)
else()
option(MITK_USE_SYSTEM_PYTHON "Use the system python runtime" OFF)
# SimpleITK is required when python is enabled
set(MITK_USE_SimpleITK ON CACHE BOOL "Use the SimpleITK library" FORCE)
if(MITK_USE_SYSTEM_PYTHON)
FIND_PACKAGE(PythonLibs REQUIRED)
FIND_PACKAGE(PythonInterp REQUIRED)
else()
FIND_PACKAGE(PythonLibs)
FIND_PACKAGE(PythonInterp)
endif()
endif()
endif()
if(MITK_USE_Boost)
option(MITK_USE_SYSTEM_Boost "Use the system Boost" OFF)
set(MITK_USE_Boost_LIBRARIES "" CACHE STRING "A semi-colon separated list of required Boost libraries")
endif()
if(MITK_USE_BLUEBERRY)
option(MITK_BUILD_ALL_PLUGINS "Build all MITK plugins" OFF)
mark_as_advanced(MITK_BUILD_ALL_PLUGINS)
if(NOT MITK_USE_CTK)
message("> Forcing MITK_USE_CTK to ON because of MITK_USE_BLUEBERRY")
set(MITK_USE_CTK ON CACHE BOOL "Use CTK in MITK" FORCE)
endif()
endif()
if(MITK_USE_CTK AND NOT MITK_USE_DCMTK)
message("> Forcing MITK_USE_DCMTK to ON because of MITK_USE_CTK")
set(MITK_USE_DCMTK ON CACHE BOOL "Use DCMTK in MITK" FORCE)
endif()
if(MITK_USE_SOFA)
# SOFA requires at least CMake 2.8.8
set(SOFA_CMAKE_VERSION 2.8.8)
if(${CMAKE_VERSION} VERSION_LESS ${SOFA_CMAKE_VERSION})
set(MITK_USE_SOFA OFF CACHE BOOL "" FORCE)
message(WARNING "Switched off MITK_USE_SOFA\n Minimum required CMake version: ${SOFA_CMAKE_VERSION}\n Installed CMake version: ${CMAKE_VERSION}")
endif()
# SOFA/ITK combination requires at least MSVC 2010
if(MSVC_VERSION AND MSVC_VERSION LESS 1600)
set(MITK_USE_SOFA OFF CACHE BOOL "" FORCE)
message(WARNING "Switched off MITK_USE_SOFA\n MSVC versions less than 2010 are not supported.")
endif()
# SOFA requires boost library
if(MITK_USE_SOFA AND NOT MITK_USE_Boost)
message("Forcing MITK_USE_Boost to ON because of MITK_USE_SOFA")
set(MITK_USE_Boost ON CACHE BOOL "" FORCE)
endif()
# SOFA requires boost system library
list(FIND MITK_USE_Boost_LIBRARIES system _result)
if(_result LESS 0)
message("Adding 'system' to MITK_USE_Boost_LIBRARIES.")
list(APPEND MITK_USE_Boost_LIBRARIES system)
endif()
# SOFA requires boost thread library
list(FIND MITK_USE_Boost_LIBRARIES thread _result)
if(_result LESS 0)
message("Adding 'thread' to MITK_USE_Boost_LIBRARIES.")
list(APPEND MITK_USE_Boost_LIBRARIES thread)
endif()
# Simulation plugin requires boost chrono library
list(FIND MITK_USE_Boost_LIBRARIES chrono _result)
if(_result LESS 0)
message("Adding 'chrono' to MITK_USE_Boost_LIBRARIES.")
list(APPEND MITK_USE_Boost_LIBRARIES chrono)
endif()
set(MITK_USE_Boost_LIBRARIES ${MITK_USE_Boost_LIBRARIES} CACHE STRING "" FORCE)
# Allow setting external SOFA plugins directory and SOFA plugins
set(MITK_USE_SOFA_PLUGINS_DIR ${MITK_USE_SOFA_PLUGINS_DIR} CACHE PATH "External SOFA plugins directory" FORCE)
set(MITK_USE_SOFA_PLUGINS ${MITK_USE_SOFA_PLUGINS} CACHE PATH "List of semicolon-separated plugin names" FORCE)
endif()
# Customize the default pixel types for multiplex macros
set(MITK_ACCESSBYITK_INTEGRAL_PIXEL_TYPES
"int, unsigned int, short, unsigned short, char, unsigned char"
CACHE STRING "List of integral pixel types used in AccessByItk and InstantiateAccessFunction macros")
set(MITK_ACCESSBYITK_FLOATING_PIXEL_TYPES
"double, float"
CACHE STRING "List of floating pixel types used in AccessByItk and InstantiateAccessFunction macros")
set(MITK_ACCESSBYITK_COMPOSITE_PIXEL_TYPES
"itk::RGBPixel, itk::RGBAPixel"
CACHE STRING "List of composite pixel types used in AccessByItk and InstantiateAccessFunction macros")
set(MITK_ACCESSBYITK_DIMENSIONS
"2,3"
CACHE STRING "List of dimensions used in AccessByItk and InstantiateAccessFunction macros")
mark_as_advanced(MITK_ACCESSBYITK_INTEGRAL_PIXEL_TYPES
MITK_ACCESSBYITK_FLOATING_PIXEL_TYPES
MITK_ACCESSBYITK_COMPOSITE_PIXEL_TYPES
MITK_ACCESSBYITK_DIMENSIONS
)
# consistency checks
if(NOT MITK_ACCESSBYITK_INTEGRAL_PIXEL_TYPES)
set(MITK_ACCESSBYITK_INTEGRAL_PIXEL_TYPES
"int, unsigned int, short, unsigned short, char, unsigned char"
CACHE STRING "List of integral pixel types used in AccessByItk and InstantiateAccessFunction macros" FORCE)
endif()
if(NOT MITK_ACCESSBYITK_FLOATING_PIXEL_TYPES)
set(MITK_ACCESSBYITK_FLOATING_PIXEL_TYPES
"double, float"
CACHE STRING "List of floating pixel types used in AccessByItk and InstantiateAccessFunction macros" FORCE)
endif()
if(NOT MITK_ACCESSBYITK_COMPOSITE_PIXEL_TYPES)
set(MITK_ACCESSBYITK_COMPOSITE_PIXEL_TYPES
"itk::RGBPixel, itk::RGBAPixel"
CACHE STRING "List of composite pixel types used in AccessByItk and InstantiateAccessFunction macros" FORCE)
endif()
if(NOT MITK_ACCESSBYITK_VECTOR_PIXEL_TYPES)
string(REPLACE "," ";" _integral_types ${MITK_ACCESSBYITK_INTEGRAL_PIXEL_TYPES})
string(REPLACE "," ";" _floating_types ${MITK_ACCESSBYITK_FLOATING_PIXEL_TYPES})
foreach(_scalar_type ${_integral_types} ${_floating_types})
set(MITK_ACCESSBYITK_VECTOR_PIXEL_TYPES
"${MITK_ACCESSBYITK_VECTOR_PIXEL_TYPES}itk::VariableLengthVector<${_scalar_type}>,")
endforeach()
string(LENGTH "${MITK_ACCESSBYITK_VECTOR_PIXEL_TYPES}" _length)
math(EXPR _length "${_length} - 1")
string(SUBSTRING "${MITK_ACCESSBYITK_VECTOR_PIXEL_TYPES}" 0 ${_length} MITK_ACCESSBYITK_VECTOR_PIXEL_TYPES)
set(MITK_ACCESSBYITK_VECTOR_PIXEL_TYPES ${MITK_ACCESSBYITK_VECTOR_PIXEL_TYPES}
CACHE STRING "List of vector pixel types used in AccessByItk and InstantiateAccessFunction macros for itk::VectorImage types" FORCE)
endif()
if(NOT MITK_ACCESSBYITK_DIMENSIONS)
set(MITK_ACCESSBYITK_DIMENSIONS
"2,3"
CACHE STRING "List of dimensions used in AccessByItk and InstantiateAccessFunction macros")
endif()
#-----------------------------------------------------------------------------
# Project.xml
#-----------------------------------------------------------------------------
# A list of topologically ordered targets
set(CTEST_PROJECT_SUBPROJECTS)
if(MITK_USE_BLUEBERRY)
list(APPEND CTEST_PROJECT_SUBPROJECTS BlueBerry)
endif()
list(APPEND CTEST_PROJECT_SUBPROJECTS
MITK-Core
MITK-CoreUI
MITK-IGT
MITK-ToF
MITK-DTI
MITK-Registration
MITK-Modules # all modules not contained in a specific subproject
MITK-Plugins # all plugins not contained in a specific subproject
MITK-Examples
Unlabeled # special "subproject" catching all unlabeled targets and tests
)
# Configure CTestConfigSubProject.cmake that could be used by CTest scripts
configure_file(${MITK_SOURCE_DIR}/CTestConfigSubProject.cmake.in
${MITK_BINARY_DIR}/CTestConfigSubProject.cmake)
if(CTEST_PROJECT_ADDITIONAL_TARGETS)
# those targets will be executed at the end of the ctest driver script
# and they also get their own subproject label
set(subproject_list "${CTEST_PROJECT_SUBPROJECTS};${CTEST_PROJECT_ADDITIONAL_TARGETS}")
else()
set(subproject_list "${CTEST_PROJECT_SUBPROJECTS}")
endif()
# Generate Project.xml file expected by the CTest driver script
mitkFunctionGenerateProjectXml(${MITK_BINARY_DIR} MITK "${subproject_list}" ${MITK_USE_SUPERBUILD})
#-----------------------------------------------------------------------------
# Superbuild script
#-----------------------------------------------------------------------------
if(MITK_USE_SUPERBUILD)
include("${CMAKE_CURRENT_SOURCE_DIR}/SuperBuild.cmake")
# Print configuration summary
message("\n\n")
feature_summary(
DESCRIPTION "------- FEATURE SUMMARY FOR ${PROJECT_NAME} -------"
WHAT ALL)
return()
endif()
#*****************************************************************************
#**************************** END OF SUPERBUILD ****************************
#*****************************************************************************
#-----------------------------------------------------------------------------
# CMake function(s) and macro(s)
#-----------------------------------------------------------------------------
include(WriteBasicConfigVersionFile)
include(CheckCXXSourceCompiles)
include(mitkFunctionCheckCompilerFlags)
include(mitkFunctionGetGccVersion)
include(MacroParseArguments)
include(mitkFunctionSuppressWarnings) # includes several functions
include(mitkFunctionOrganizeSources)
include(mitkFunctionGetVersion)
include(mitkFunctionGetVersionDescription)
include(mitkFunctionCreateWindowsBatchScript)
include(mitkFunctionInstallProvisioningFiles)
include(mitkFunctionInstallAutoLoadModules)
include(mitkFunctionGetLibrarySearchPaths)
include(mitkFunctionCompileSnippets)
include(mitkFunctionUseModules)
include(mitkMacroCreateModuleConf)
include(mitkFunctionCheckModuleDependencies)
include(mitkFunctionCreateModule)
include(mitkMacroCreateExecutable)
include(mitkMacroCheckModule)
include(mitkMacroCreateModuleTests)
include(mitkFunctionAddCustomModuleTest)
include(mitkMacroUseModule)
include(mitkMacroMultiplexPicType)
include(mitkMacroInstall)
include(mitkMacroInstallHelperApp)
include(mitkMacroInstallTargets)
include(mitkMacroGenerateToolsLibrary)
include(mitkMacroGetLinuxDistribution)
include(mitkMacroGetPMDPlatformString)
#-----------------------------------------------------------------------------
# Set MITK specific options and variables (NOT available during superbuild)
#-----------------------------------------------------------------------------
# ASK THE USER TO SHOW THE CONSOLE WINDOW FOR CoreApp and mitkWorkbench
option(MITK_SHOW_CONSOLE_WINDOW "Use this to enable or disable the console window when starting MITK GUI Applications" ON)
mark_as_advanced(MITK_SHOW_CONSOLE_WINDOW)
# TODO: check if necessary
option(USE_ITKZLIB "Use the ITK zlib for pic compression." ON)
mark_as_advanced(USE_ITKZLIB)
if(NOT MITK_FAST_TESTING)
if(DEFINED MITK_CTEST_SCRIPT_MODE
AND (MITK_CTEST_SCRIPT_MODE STREQUAL "continuous" OR MITK_CTEST_SCRIPT_MODE STREQUAL "experimental") )
set(MITK_FAST_TESTING 1)
endif()
endif()
#-----------------------------------------------------------------------------
# Get MITK version info
#-----------------------------------------------------------------------------
mitkFunctionGetVersion(${MITK_SOURCE_DIR} MITK)
mitkFunctionGetVersionDescription(${MITK_SOURCE_DIR} MITK)
#-----------------------------------------------------------------------------
# Installation preparation
#
# These should be set before any MITK install macros are used
#-----------------------------------------------------------------------------
# on Mac OSX all BlueBerry plugins get copied into every
# application bundle (.app directory) specified here
if(MITK_USE_BLUEBERRY AND APPLE)
include("${CMAKE_CURRENT_SOURCE_DIR}/Applications/AppList.cmake")
foreach(mitk_app ${MITK_APPS})
# extract option_name
string(REPLACE "^^" "\\;" target_info ${mitk_app})
set(target_info_list ${target_info})
list(GET target_info_list 1 option_name)
list(GET target_info_list 0 app_name)
# check if the application is enabled
if(${option_name} OR MITK_BUILD_ALL_APPS)
set(MACOSX_BUNDLE_NAMES ${MACOSX_BUNDLE_NAMES} Mitk${app_name})
endif()
endforeach()
endif()
#-----------------------------------------------------------------------------
# Set symbol visibility Flags
#-----------------------------------------------------------------------------
# MinGW does not export all symbols automatically, so no need to set flags
if(CMAKE_COMPILER_IS_GNUCXX AND NOT MINGW)
set(VISIBILITY_CXX_FLAGS ) #"-fvisibility=hidden -fvisibility-inlines-hidden")
endif()
#-----------------------------------------------------------------------------
# Set coverage Flags
#-----------------------------------------------------------------------------
if(WITH_COVERAGE)
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
set(coverage_flags "-g -fprofile-arcs -ftest-coverage -O0 -DNDEBUG")
set(COVERAGE_CXX_FLAGS ${coverage_flags})
set(COVERAGE_C_FLAGS ${coverage_flags})
endif()
endif()
#-----------------------------------------------------------------------------
# MITK C/CXX Flags
#-----------------------------------------------------------------------------
set(MITK_C_FLAGS "${COVERAGE_C_FLAGS}")
set(MITK_C_FLAGS_DEBUG )
set(MITK_C_FLAGS_RELEASE )
set(MITK_CXX_FLAGS "${VISIBILITY_CXX_FLAGS} ${COVERAGE_CXX_FLAGS}")
set(MITK_CXX_FLAGS_DEBUG )
set(MITK_CXX_FLAGS_RELEASE )
set(MITK_EXE_LINKER_FLAGS )
set(MITK_SHARED_LINKER_FLAGS )
if(WIN32)
set(MITK_CXX_FLAGS "${MITK_CXX_FLAGS} -D_WIN32_WINNT=0x0501 -DPOCO_NO_UNWINDOWS -DWIN32_LEAN_AND_MEAN -DNOMINMAX")
set(MITK_CXX_FLAGS "${MITK_CXX_FLAGS} /wd4231") # warning C4231: nonstandard extension used : 'extern' before template explicit instantiation
# the following line should be removed after fixing bug 17637
mitkFunctionCheckCompilerFlags("/wd4316" MITK_CXX_FLAGS) # warning C4316: object alignment on heap
endif()
if(NOT MSVC_VERSION)
foreach(_flag
-Wall
-Wextra
-Wpointer-arith
-Winvalid-pch
-Wcast-align
-Wwrite-strings
-Wno-error=gnu
-Wno-error=unknown-pragmas
# The strict-overflow warning is generated by ITK template code
-Wno-error=strict-overflow
-Woverloaded-virtual
-Wstrict-null-sentinel
#-Wold-style-cast
#-Wsign-promo
# the following two lines should be removed after ITK-3097 has
# been resolved, see also MITK bug 15279
-Wno-unused-local-typedefs
-Wno-array-bounds
-fdiagnostics-show-option
)
mitkFunctionCheckCAndCXXCompilerFlags(${_flag} MITK_C_FLAGS MITK_CXX_FLAGS)
endforeach()
endif()
if(CMAKE_COMPILER_IS_GNUCXX AND NOT APPLE)
mitkFunctionCheckCompilerFlags("-Wl,--no-undefined" MITK_SHARED_LINKER_FLAGS)
mitkFunctionCheckCompilerFlags("-Wl,--as-needed" MITK_SHARED_LINKER_FLAGS)
endif()
if(CMAKE_COMPILER_IS_GNUCXX)
mitkFunctionGetGccVersion(${CMAKE_CXX_COMPILER} GCC_VERSION)
# With older version of gcc supporting the flag -fstack-protector-all, an extra dependency to libssp.so
# is introduced. If gcc is smaller than 4.4.0 and the build type is Release let's not include the flag.
# Doing so should allow to build package made for distribution using older linux distro.
if(${GCC_VERSION} VERSION_GREATER "4.4.0" OR (CMAKE_BUILD_TYPE STREQUAL "Debug" AND ${GCC_VERSION} VERSION_LESS "4.4.0"))
mitkFunctionCheckCAndCXXCompilerFlags("-fstack-protector-all" MITK_C_FLAGS MITK_CXX_FLAGS)
endif()
if(MINGW)
# suppress warnings about auto imported symbols
set(MITK_SHARED_LINKER_FLAGS "-Wl,--enable-auto-import ${MITK_SHARED_LINKER_FLAGS}")
endif()
set(MITK_CXX_FLAGS_RELEASE "-D_FORTIFY_SOURCE=2 ${MITK_CXX_FLAGS_RELEASE}")
endif()
set(MITK_MODULE_LINKER_FLAGS ${MITK_SHARED_LINKER_FLAGS})
set(MITK_EXE_LINKER_FLAGS ${MITK_SHARED_LINKER_FLAGS})
#-----------------------------------------------------------------------------
# MITK Packages
#-----------------------------------------------------------------------------
set(MITK_MODULES_PACKAGE_DEPENDS_DIR ${MITK_SOURCE_DIR}/CMake/PackageDepends)
set(MODULES_PACKAGE_DEPENDS_DIRS ${MITK_MODULES_PACKAGE_DEPENDS_DIR})
#-----------------------------------------------------------------------------
# Testing
#-----------------------------------------------------------------------------
if(BUILD_TESTING)
enable_testing()
include(CTest)
mark_as_advanced(TCL_TCLSH DART_ROOT)
option(MITK_ENABLE_RENDERING_TESTING OFF "Enable the MITK rendering tests. Requires x-server in Linux.")
#Rendering testing does not work for Linux nightlies, thus it is disabled per default
#and activated for Mac and Windows.
if(WIN32 OR APPLE)
set(MITK_ENABLE_RENDERING_TESTING ON)
endif()
mark_as_advanced( MITK_ENABLE_RENDERING_TESTING )
# Setup file for setting custom ctest vars
configure_file(
CMake/CTestCustom.cmake.in
${MITK_BINARY_DIR}/CTestCustom.cmake
@ONLY
)
# Configuration for the CMake-generated test driver
set(CMAKE_TESTDRIVER_EXTRA_INCLUDES "#include ")
set(CMAKE_TESTDRIVER_BEFORE_TESTMAIN "
try
{")
set(CMAKE_TESTDRIVER_AFTER_TESTMAIN " }
catch( std::exception & excp )
{
fprintf(stderr,\"%s\\n\",excp.what());
return EXIT_FAILURE;
}
catch( ... )
{
printf(\"Exception caught in the test driver\\n\");
return EXIT_FAILURE;
}
")
set(MITK_TEST_OUTPUT_DIR "${MITK_BINARY_DIR}/test_output")
if(NOT EXISTS ${MITK_TEST_OUTPUT_DIR})
file(MAKE_DIRECTORY ${MITK_TEST_OUTPUT_DIR})
endif()
# Test the external project template
if(MITK_USE_BLUEBERRY)
include(mitkTestProjectTemplate)
endif()
# Test the package target
include(mitkPackageTest)
endif()
configure_file(mitkTestingConfig.h.in ${MITK_BINARY_DIR}/mitkTestingConfig.h)
#-----------------------------------------------------------------------------
# MITK_SUPERBUILD_BINARY_DIR
#-----------------------------------------------------------------------------
# If MITK_SUPERBUILD_BINARY_DIR isn't defined, it means MITK is *NOT* build using Superbuild.
# In that specific case, MITK_SUPERBUILD_BINARY_DIR should default to MITK_BINARY_DIR
if(NOT DEFINED MITK_SUPERBUILD_BINARY_DIR)
set(MITK_SUPERBUILD_BINARY_DIR ${MITK_BINARY_DIR})
endif()
#-----------------------------------------------------------------------------
# Compile Utilities and set-up MITK variables
#-----------------------------------------------------------------------------
include(mitkSetupVariables)
#-----------------------------------------------------------------------------
# Cleanup
#-----------------------------------------------------------------------------
file(GLOB _MODULES_CONF_FILES ${PROJECT_BINARY_DIR}/${MODULES_CONF_DIRNAME}/*.cmake)
if(_MODULES_CONF_FILES)
file(REMOVE ${_MODULES_CONF_FILES})
endif()
add_subdirectory(Utilities)
if(MITK_USE_BLUEBERRY)
# We need to hack a little bit because MITK applications may need
# to enable certain BlueBerry plug-ins. However, these plug-ins
# are validated separately from the MITK plug-ins and know nothing
# about potential MITK plug-in dependencies of the applications. Hence
# we cannot pass the MITK application list to the BlueBerry
# ctkMacroSetupPlugins call but need to extract the BlueBerry dependencies
# from the applications and set them explicitly.
include("${CMAKE_CURRENT_SOURCE_DIR}/Applications/AppList.cmake")
foreach(mitk_app ${MITK_APPS})
# extract target_dir and option_name
string(REPLACE "^^" "\\;" target_info ${mitk_app})
set(target_info_list ${target_info})
list(GET target_info_list 0 target_dir)
list(GET target_info_list 1 option_name)
# check if the application is enabled and if target_libraries.cmake exists
if((${option_name} OR MITK_BUILD_ALL_APPS) AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/Applications/${target_dir}/target_libraries.cmake")
include("${CMAKE_CURRENT_SOURCE_DIR}/Applications/${target_dir}/target_libraries.cmake")
foreach(_target_dep ${target_libraries})
if(_target_dep MATCHES org_blueberry_)
string(REPLACE _ . _app_bb_dep ${_target_dep})
# explicitly set the build option for the BlueBerry plug-in
set(BLUEBERRY_BUILD_${_app_bb_dep} ON CACHE BOOL "Build the ${_app_bb_dep} plug-in")
endif()
endforeach()
endif()
endforeach()
set(mbilog_DIR "${mbilog_BINARY_DIR}")
if(MITK_BUILD_ALL_PLUGINS)
set(BLUEBERRY_BUILD_ALL_PLUGINS ON)
endif()
set(BLUEBERRY_XPDOC_OUTPUT_DIR ${MITK_DOXYGEN_OUTPUT_DIR}/html/extension-points/html/)
add_subdirectory(BlueBerry)
set(BlueBerry_DIR ${CMAKE_CURRENT_BINARY_DIR}/BlueBerry
CACHE PATH "The directory containing a CMake configuration file for BlueBerry" FORCE)
include(mitkMacroCreateCTKPlugin)
endif()
#-----------------------------------------------------------------------------
# Set C/CXX and linker flags for MITK code
#-----------------------------------------------------------------------------
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${MITK_CXX_FLAGS}")
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} ${MITK_CXX_FLAGS_DEBUG}")
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} ${MITK_CXX_FLAGS_RELEASE}")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${MITK_C_FLAGS}")
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} ${MITK_C_FLAGS_DEBUG}")
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} ${MITK_C_FLAGS_RELEASE}")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${MITK_EXE_LINKER_FLAGS}")
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${MITK_SHARED_LINKER_FLAGS}")
set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} ${MITK_MODULE_LINKER_FLAGS}")
#-----------------------------------------------------------------------------
# Add custom targets representing CDash subprojects
#-----------------------------------------------------------------------------
foreach(subproject ${CTEST_PROJECT_SUBPROJECTS})
if(NOT TARGET ${subproject} AND NOT subproject MATCHES "Unlabeled")
add_custom_target(${subproject})
endif()
endforeach()
#-----------------------------------------------------------------------------
# Add subdirectories
#-----------------------------------------------------------------------------
add_subdirectory(Core)
add_subdirectory(Modules)
if(MITK_USE_BLUEBERRY)
find_package(BlueBerry REQUIRED)
set(MITK_DEFAULT_SUBPROJECTS MITK-Plugins)
# Plug-in testing (needs some work to be enabled again)
if(BUILD_TESTING)
include(berryTestingHelpers)
set(BLUEBERRY_UI_TEST_APP "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/CoreApp")
get_target_property(_is_macosx_bundle CoreApp MACOSX_BUNDLE)
if(APPLE AND _is_macosx_bundle)
set(BLUEBERRY_UI_TEST_APP "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/CoreApp.app/Contents/MacOS/CoreApp")
endif()
set(BLUEBERRY_TEST_APP_ID "org.mitk.qt.coreapplication")
endif()
include("${CMAKE_CURRENT_SOURCE_DIR}/Plugins/PluginList.cmake")
set(mitk_plugins_fullpath )
foreach(mitk_plugin ${MITK_EXT_PLUGINS})
list(APPEND mitk_plugins_fullpath Plugins/${mitk_plugin})
endforeach()
if(EXISTS ${MITK_PRIVATE_MODULES}/PluginList.cmake)
include(${MITK_PRIVATE_MODULES}/PluginList.cmake)
foreach(mitk_plugin ${MITK_PRIVATE_PLUGINS})
list(APPEND mitk_plugins_fullpath ${MITK_PRIVATE_MODULES}/${mitk_plugin})
endforeach()
endif()
if(MITK_BUILD_EXAMPLES)
include("${CMAKE_CURRENT_SOURCE_DIR}/Examples/Plugins/PluginList.cmake")
set(mitk_example_plugins_fullpath )
foreach(mitk_example_plugin ${MITK_EXAMPLE_PLUGINS})
list(APPEND mitk_example_plugins_fullpath Examples/Plugins/${mitk_example_plugin})
list(APPEND mitk_plugins_fullpath Examples/Plugins/${mitk_example_plugin})
endforeach()
endif()
# Specify which plug-ins belong to this project
macro(GetMyTargetLibraries all_target_libraries varname)
set(re_ctkplugin_mitk "^org_mitk_[a-zA-Z0-9_]+$")
set(re_ctkplugin_bb "^org_blueberry_[a-zA-Z0-9_]+$")
set(_tmp_list)
list(APPEND _tmp_list ${all_target_libraries})
ctkMacroListFilter(_tmp_list re_ctkplugin_mitk re_ctkplugin_bb OUTPUT_VARIABLE ${varname})
endmacro()
# Get infos about application directories and build options
include("${CMAKE_CURRENT_SOURCE_DIR}/Applications/AppList.cmake")
set(mitk_apps_fullpath )
foreach(mitk_app ${MITK_APPS})
list(APPEND mitk_apps_fullpath "${CMAKE_CURRENT_SOURCE_DIR}/Applications/${mitk_app}")
endforeach()
if (mitk_plugins_fullpath)
ctkMacroSetupPlugins(${mitk_plugins_fullpath}
BUILD_OPTION_PREFIX MITK_BUILD_
APPS ${mitk_apps_fullpath}
BUILD_ALL ${MITK_BUILD_ALL_PLUGINS}
COMPACT_OPTIONS)
endif()
set(MITK_PLUGIN_USE_FILE "${MITK_BINARY_DIR}/MitkPluginUseFile.cmake")
if(${PROJECT_NAME}_PLUGIN_LIBRARIES)
ctkFunctionGeneratePluginUseFile(${MITK_PLUGIN_USE_FILE})
else()
file(REMOVE ${MITK_PLUGIN_USE_FILE})
set(MITK_PLUGIN_USE_FILE )
endif()
# 11.3.13, change, muellerm: activate python bundle if python and blueberry is active
if( MITK_USE_Python )
set(MITK_BUILD_org.mitk.gui.qt.python ON)
endif()
endif()
#-----------------------------------------------------------------------------
# Documentation
#-----------------------------------------------------------------------------
add_subdirectory(Documentation)
#-----------------------------------------------------------------------------
# Installation
#-----------------------------------------------------------------------------
# set MITK cpack variables
# These are the default variables, which can be overwritten ( see below )
include(mitkSetupCPack)
set(use_default_config ON)
# MITK_APPS is set in Applications/AppList.cmake (included somewhere above
# if MITK_USE_BLUEBERRY is set to ON).
if(MITK_APPS)
set(activated_apps_no 0)
list(LENGTH MITK_APPS app_count)
# Check how many apps have been enabled
# If more than one app has been activated, the we use the
# default CPack configuration. Otherwise that apps configuration
# will be used, if present.
foreach(mitk_app ${MITK_APPS})
# extract option_name
string(REPLACE "^^" "\\;" target_info ${mitk_app})
set(target_info_list ${target_info})
list(GET target_info_list 1 option_name)
# check if the application is enabled
if(${option_name} OR MITK_BUILD_ALL_APPS)
MATH(EXPR activated_apps_no "${activated_apps_no} + 1")
endif()
endforeach()
if(app_count EQUAL 1 AND (activated_apps_no EQUAL 1 OR MITK_BUILD_ALL_APPS))
# Corner case if there is only one app in total
set(use_project_cpack ON)
elseif(activated_apps_no EQUAL 1 AND NOT MITK_BUILD_ALL_APPS)
# Only one app is enabled (no "build all" flag set)
set(use_project_cpack ON)
else()
# Less or more then one app is enabled
set(use_project_cpack OFF)
endif()
foreach(mitk_app ${MITK_APPS})
# extract target_dir and option_name
string(REPLACE "^^" "\\;" target_info ${mitk_app})
set(target_info_list ${target_info})
list(GET target_info_list 0 target_dir)
list(GET target_info_list 1 option_name)
# check if the application is enabled
if(${option_name} OR MITK_BUILD_ALL_APPS)
# check whether application specific configuration files will be used
if(use_project_cpack)
# use files if they exist
if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/Applications/${target_dir}/CPackOptions.cmake")
include("${CMAKE_CURRENT_SOURCE_DIR}/Applications/${target_dir}/CPackOptions.cmake")
endif()
if(EXISTS "${PROJECT_SOURCE_DIR}/Applications/${target_dir}/CPackConfig.cmake.in")
set(CPACK_PROJECT_CONFIG_FILE "${PROJECT_BINARY_DIR}/Applications/${target_dir}/CPackConfig.cmake")
configure_file(${PROJECT_SOURCE_DIR}/Applications/${target_dir}/CPackConfig.cmake.in
${CPACK_PROJECT_CONFIG_FILE} @ONLY)
set(use_default_config OFF)
endif()
endif()
# add link to the list
list(APPEND CPACK_CREATE_DESKTOP_LINKS "${target_dir}")
endif()
endforeach()
endif()
# if no application specific configuration file was used, use default
if(use_default_config)
configure_file(${MITK_SOURCE_DIR}/MITKCPackOptions.cmake.in
${MITK_BINARY_DIR}/MITKCPackOptions.cmake @ONLY)
set(CPACK_PROJECT_CONFIG_FILE "${MITK_BINARY_DIR}/MITKCPackOptions.cmake")
endif()
# include CPack model once all variables are set
include(CPack)
# Additional installation rules
include(mitkInstallRules)
#-----------------------------------------------------------------------------
# Last configuration steps
#-----------------------------------------------------------------------------
set(MITK_EXPORTS_FILE "${MITK_BINARY_DIR}/MitkExports.cmake")
file(REMOVE ${MITK_EXPORTS_FILE})
set(targets_to_export)
get_property(module_targets GLOBAL PROPERTY MITK_MODULE_TARGETS)
if(module_targets)
list(APPEND targets_to_export ${module_targets})
endif()
if(MITK_USE_BLUEBERRY)
if(MITK_PLUGIN_LIBRARIES)
list(APPEND targets_to_export ${MITK_PLUGIN_LIBRARIES})
endif()
endif()
export(TARGETS ${targets_to_export} APPEND
FILE ${MITK_EXPORTS_FILE})
set(MITK_EXPORTED_TARGET_PROPERTIES )
foreach(target_to_export ${targets_to_export})
get_target_property(autoload_targets ${target_to_export} MITK_AUTOLOAD_TARGETS)
if(autoload_targets)
set(MITK_EXPORTED_TARGET_PROPERTIES "${MITK_EXPORTED_TARGET_PROPERTIES}
set_target_properties(${target_to_export} PROPERTIES MITK_AUTOLOAD_TARGETS \"${autoload_targets}\")")
endif()
get_target_property(autoload_dir ${target_to_export} MITK_AUTOLOAD_DIRECTORY)
if(autoload_dir)
set(MITK_EXPORTED_TARGET_PROPERTIES "${MITK_EXPORTED_TARGET_PROPERTIES}
set_target_properties(${target_to_export} PROPERTIES MITK_AUTOLOAD_DIRECTORY \"${autoload_dir}\")")
endif()
endforeach()
get_property(MITK_ADDITIONAL_LIBRARY_SEARCH_PATHS_CONFIG GLOBAL PROPERTY MITK_ADDITIONAL_LIBRARY_SEARCH_PATHS)
configure_file(${MITK_SOURCE_DIR}/CMake/ToolExtensionITKFactory.cpp.in
${MITK_BINARY_DIR}/ToolExtensionITKFactory.cpp.in COPYONLY)
configure_file(${MITK_SOURCE_DIR}/CMake/ToolExtensionITKFactoryLoader.cpp.in
${MITK_BINARY_DIR}/ToolExtensionITKFactoryLoader.cpp.in COPYONLY)
configure_file(${MITK_SOURCE_DIR}/CMake/ToolGUIExtensionITKFactory.cpp.in
${MITK_BINARY_DIR}/ToolGUIExtensionITKFactory.cpp.in COPYONLY)
set(VISIBILITY_AVAILABLE 0)
set(visibility_test_flag "")
mitkFunctionCheckCompilerFlags("-fvisibility=hidden" visibility_test_flag)
if(visibility_test_flag)
# The compiler understands -fvisiblity=hidden (probably gcc >= 4 or Clang)
set(VISIBILITY_AVAILABLE 1)
endif()
configure_file(mitkExportMacros.h.in ${MITK_BINARY_DIR}/mitkExportMacros.h)
configure_file(mitkVersion.h.in ${MITK_BINARY_DIR}/mitkVersion.h)
configure_file(mitkConfig.h.in ${MITK_BINARY_DIR}/mitkConfig.h)
set(IPFUNC_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/Utilities/ipFunc)
set(UTILITIES_DIR ${CMAKE_CURRENT_SOURCE_DIR}/Utilities)
file(GLOB _MODULES_CONF_FILES RELATIVE ${PROJECT_BINARY_DIR}/${MODULES_CONF_DIRNAME} ${PROJECT_BINARY_DIR}/${MODULES_CONF_DIRNAME}/*.cmake)
set(MITK_MODULE_NAMES)
foreach(_module ${_MODULES_CONF_FILES})
string(REPLACE Config.cmake "" _module_name ${_module})
list(APPEND MITK_MODULE_NAMES ${_module_name})
endforeach()
configure_file(mitkConfig.h.in ${MITK_BINARY_DIR}/mitkConfig.h)
configure_file(MITKConfig.cmake.in ${MITK_BINARY_DIR}/MITKConfig.cmake @ONLY)
write_basic_config_version_file(${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake
VERSION ${MITK_VERSION_STRING} COMPATIBILITY AnyNewerVersion)
# If we are under Windows, create two batch files which correctly
# set up the environment for the application and for Visual Studio
if(WIN32)
include(mitkFunctionCreateWindowsBatchScript)
set(VS_SOLUTION_FILE "${PROJECT_BINARY_DIR}/${PROJECT_NAME}.sln")
foreach(VS_BUILD_TYPE debug release)
mitkFunctionCreateWindowsBatchScript("${MITK_SOURCE_DIR}/CMake/StartVS.bat.in"
${PROJECT_BINARY_DIR}/StartVS_${VS_BUILD_TYPE}.bat
${VS_BUILD_TYPE})
endforeach()
endif(WIN32)
#-----------------------------------------------------------------------------
# MITK Applications
#-----------------------------------------------------------------------------
# This must come after MITKConfig.h was generated, since applications
# might do a find_package(MITK REQUIRED).
add_subdirectory(Applications)
#-----------------------------------------------------------------------------
# MITK Examples
#-----------------------------------------------------------------------------
if(MITK_BUILD_EXAMPLES)
# This must come after MITKConfig.h was generated, since applications
# might do a find_package(MITK REQUIRED).
add_subdirectory(Examples)
endif()
#-----------------------------------------------------------------------------
# Print configuration summary
#-----------------------------------------------------------------------------
message("\n\n")
feature_summary(
DESCRIPTION "------- FEATURE SUMMARY FOR ${PROJECT_NAME} -------"
WHAT ALL
)
diff --git a/Core/CMakeLists.txt b/Core/CMakeLists.txt
index 181090590a..ae64924278 100644
--- a/Core/CMakeLists.txt
+++ b/Core/CMakeLists.txt
@@ -1,48 +1,50 @@
#-----------------------------------------------------------------------------
# Configure the CppMicroServices build
#-----------------------------------------------------------------------------
set(US_ENABLE_AUTOLOADING_SUPPORT ON)
set(US_ENABLE_THREADING_SUPPORT ON)
# Don't create a "doc" target and don't install the documentation files
set(US_NO_DOCUMENTATION ON)
# Don't use an install component for SDK artifacts
set(US_SDK_INSTALL_COMPONENT "")
if(BUILD_TESTING)
set(US_BUILD_TESTING ON)
endif()
set(CppMicroServices_DIR_default "${CMAKE_CURRENT_BINARY_DIR}/CppMicroServices")
-set(CppMicroServices_DIR ${CppMicroServices_DIR_default} CACHE PATH "Path to the CppMicroServices library")
+if(NOT CppMicroServices_DIR)
+ set(CppMicroServices_DIR ${CppMicroServices_DIR_default} CACHE PATH "Path to the CppMicroServices library" FORCE)
+endif()
mark_as_advanced(CppMicroServices_DIR)
if ("${CppMicroServices_DIR}" STREQUAL "${CppMicroServices_DIR_default}")
add_subdirectory(CppMicroServices)
endif()
# create a custom module conf file for CppMicroServices
function(_generate_cppmicroservices_conf)
set(MITK_MODULE_NAME_PREFIX "")
set(MODULE_IS_ENABLED 1)
set(MODULE_NAME CppMicroServices)
set(MODULE_TARGET ${MODULE_NAME})
set(MODULE_EXTRA_CMAKE_CODE "find_package(CppMicroServices NO_MODULE REQUIRED)")
set(MODULE_INCLUDE_DIRS "\${CppMicroServices_INCLUDE_DIRS}")
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "\${US_RUNTIME_LIBRARY_DIRS}")
set(CppMicroServices_CONFIG_FILE "${CMAKE_BINARY_DIR}/${MODULES_CONF_DIRNAME}/CppMicroServicesConfig.cmake" CACHE INTERNAL "Path to module config" FORCE)
configure_file(${MITK_SOURCE_DIR}/CMake/moduleConf.cmake.in ${CppMicroServices_CONFIG_FILE} @ONLY)
endfunction()
_generate_cppmicroservices_conf()
#-----------------------------------------------------------------------------
# Add the MITK Core library
#-----------------------------------------------------------------------------
set(MITK_DEFAULT_SUBPROJECTS MITK-Core)
add_subdirectory(Code)
diff --git a/Core/Code/Common/mitkCoreServices.h b/Core/Code/Common/mitkCoreServices.h
index 752f5b7119..d22ca60bd0 100644
--- a/Core/Code/Common/mitkCoreServices.h
+++ b/Core/Code/Common/mitkCoreServices.h
@@ -1,178 +1,178 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
Copyright (c) German Cancer Research Center,
Division of Medical and Biological Informatics.
All rights reserved.
This software is distributed WITHOUT ANY WARRANTY; without
even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE.
See LICENSE.txt or http://www.mitk.org for details.
===================================================================*/
#ifndef MITKCORESERVICES_H
#define MITKCORESERVICES_H
#include "MitkCoreExports.h"
#include
#include
#include
-#include
+#include
#include
#include
namespace mitk {
struct IMimeTypeProvider;
struct IShaderRepository;
class IPropertyAliases;
class IPropertyDescriptions;
class IPropertyExtensions;
class IPropertyFilters;
/**
* @brief Access MITK core services.
*
* This class can be used to conveniently access common
* MITK Core service objects. Some getter methods where implementations
* exist in the core library are guaranteed to return a non-NULL service object.
*
* To ensure that CoreServices::Unget() is called after the caller
* has finished using a service object, you should use the CoreServicePointer
* helper class which calls Unget() when it goes out of scope:
*
* \code
* CoreServicePointer shaderRepo(CoreServices::GetShaderRepository());
* // Do something with shaderRepo
* \endcode
*
* @see CoreServicePointer
*/
class MITK_CORE_EXPORT CoreServices
{
public:
/**
* @brief Get an IShaderRepository instance.
* @param context The module context of the module getting the service.
* @return A IShaderRepository instance which can be NULL.
*/
static IShaderRepository* GetShaderRepository();
/**
* @brief Get an IPropertyAliases instance.
* @param context The module context of the module getting the service.
* @return A non-NULL IPropertyAliases instance.
*/
static IPropertyAliases* GetPropertyAliases(us::ModuleContext* context = us::GetModuleContext());
/**
* @brief Get an IPropertyDescriptions instance.
* @param context The module context of the module getting the service.
* @return A non-NULL IPropertyDescriptions instance.
*/
static IPropertyDescriptions* GetPropertyDescriptions(us::ModuleContext* context = us::GetModuleContext());
/**
* @brief Get an IPropertyExtensions instance.
* @param context The module context of the module getting the service.
* @return A non-NULL IPropertyExtensions instance.
*/
static IPropertyExtensions* GetPropertyExtensions(us::ModuleContext* context = us::GetModuleContext());
/**
* @brief Get an IPropertyFilters instance.
* @param context The module context of the module getting the service.
* @return A non-NULL IPropertyFilters instance.
*/
static IPropertyFilters* GetPropertyFilters(us::ModuleContext* context = us::GetModuleContext());
/**
* @brief Get an IMimeTypeProvider instance.
* @param context The module context of the module getting the service.
* @return A non-NULL IMimeTypeProvider instance.
*/
static IMimeTypeProvider* GetMimeTypeProvider(us::ModuleContext* context = us::GetModuleContext());
/**
* @brief Unget a previously acquired service instance.
* @param service The service instance to be released.
* @return \c true if ungetting the service was successful, \c false otherwise.
*/
template
static bool Unget(S* service, us::ModuleContext* context = us::GetModuleContext())
{
return Unget(context, us_service_interface_iid(), service);
}
private:
static bool Unget(us::ModuleContext* context, const std::string& interfaceId, void* service);
// purposely not implemented
CoreServices();
CoreServices(const CoreServices&);
CoreServices& operator=(const CoreServices&);
};
/**
* @brief A RAII helper class for core service objects.
*
* This is class is intended for usage in local scopes; it calls
* CoreServices::Unget(S*) in its destructor. You should not construct
* multiple CoreServicePointer instances using the same service pointer,
* unless it is retrieved by a new call to a CoreServices getter method.
*
* @see CoreServices
*/
template
class CoreServicePointer
{
public:
explicit CoreServicePointer(S* service)
: m_service(service)
{
assert(m_service);
}
~CoreServicePointer()
{
try
{
CoreServices::Unget(m_service);
}
catch (const std::exception& e)
{
MITK_ERROR << e.what();
}
catch (...)
{
MITK_ERROR << "Ungetting core service failed.";
}
}
S* operator->() const
{
return m_service;
}
private:
// purposely not implemented
CoreServicePointer(const CoreServicePointer&);
CoreServicePointer& operator=(const CoreServicePointer&);
S* const m_service;
};
}
#endif // MITKCORESERVICES_H
diff --git a/Modules/SceneSerialization/mitkSceneDataNodeReader.h b/Core/Code/Common/mitkServiceInterface.h
similarity index 57%
copy from Modules/SceneSerialization/mitkSceneDataNodeReader.h
copy to Core/Code/Common/mitkServiceInterface.h
index 58320d7e5e..c5ec79e154 100644
--- a/Modules/SceneSerialization/mitkSceneDataNodeReader.h
+++ b/Core/Code/Common/mitkServiceInterface.h
@@ -1,35 +1,34 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
Copyright (c) German Cancer Research Center,
Division of Medical and Biological Informatics.
All rights reserved.
This software is distributed WITHOUT ANY WARRANTY; without
even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE.
See LICENSE.txt or http://www.mitk.org for details.
===================================================================*/
+#ifndef mitkServiceInterface_h
+#define mitkServiceInterface_h
-#ifndef MITKSCENEDATANODEREADER_H
-#define MITKSCENEDATANODEREADER_H
+#include
-#include
+#ifdef Q_DECLARE_INTERFACE
-namespace mitk {
+#define MITK_DECLARE_SERVICE_INTERFACE(IFace, IId) \
+ US_DECLARE_SERVICE_INTERFACE(IFace, IId) \
+ Q_DECLARE_INTERFACE(IFace, IId)
-class SceneDataNodeReader : public mitk::IDataNodeReader
-{
+#else
-public:
+#define MITK_DECLARE_SERVICE_INTERFACE(IFace, IId) US_DECLARE_SERVICE_INTERFACE(IFace, IId)
- int Read(const std::string& fileName, mitk::DataStorage& storage);
-};
+#endif
-}
-
-#endif // MITKSCENEDATANODEREADER_H
+#endif
diff --git a/Core/Code/Controllers/mitkCoreActivator.cpp b/Core/Code/Controllers/mitkCoreActivator.cpp
deleted file mode 100644
index 86a0121d77..0000000000
--- a/Core/Code/Controllers/mitkCoreActivator.cpp
+++ /dev/null
@@ -1,308 +0,0 @@
-/*===================================================================
-
-The Medical Imaging Interaction Toolkit (MITK)
-
-Copyright (c) German Cancer Research Center,
-Division of Medical and Biological Informatics.
-All rights reserved.
-
-This software is distributed WITHOUT ANY WARRANTY; without
-even the implied warranty of MERCHANTABILITY or FITNESS FOR
-A PARTICULAR PURPOSE.
-
-See LICENSE.txt or http://www.mitk.org for details.
-
-===================================================================*/
-
-#include "mitkRenderingManager.h"
-#include "mitkPlanePositionManager.h"
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-void HandleMicroServicesMessages(us::MsgType type, const char* msg)
-{
- switch (type)
- {
- case us::DebugMsg:
- MITK_DEBUG << msg;
- break;
- case us::InfoMsg:
- MITK_INFO << msg;
- break;
- case us::WarningMsg:
- MITK_WARN << msg;
- break;
- case us::ErrorMsg:
- MITK_ERROR << msg;
- break;
- }
-}
-
-void AddMitkAutoLoadPaths(const std::string& programPath)
-{
- us::ModuleSettings::AddAutoLoadPath(programPath);
-#ifdef __APPLE__
- // Walk up three directories since that is where the .dylib files are located
- // for build trees.
- std::string additionalPath = programPath;
- bool addPath = true;
- for(int i = 0; i < 3; ++i)
- {
- std::size_t index = additionalPath.find_last_of('/');
- if (index != std::string::npos)
- {
- additionalPath = additionalPath.substr(0, index);
- }
- else
- {
- addPath = false;
- break;
- }
- }
- if (addPath)
- {
- us::ModuleSettings::AddAutoLoadPath(additionalPath);
- }
-#endif
-}
-
-class ShaderRepositoryTracker : public us::ServiceTracker
-{
-
-public:
-
- ShaderRepositoryTracker()
- : Superclass(us::GetModuleContext())
- {
- }
-
- virtual void Close()
- {
- us::GetModuleContext()->RemoveModuleListener(this, &ShaderRepositoryTracker::HandleModuleEvent);
- Superclass::Close();
- }
-
- virtual void Open()
- {
- us::GetModuleContext()->AddModuleListener(this, &ShaderRepositoryTracker::HandleModuleEvent);
- Superclass::Open();
- }
-
-private:
-
- typedef us::ServiceTracker Superclass;
-
- TrackedType AddingService(const ServiceReferenceType &reference)
- {
- mitk::IShaderRepository* shaderRepo = Superclass::AddingService(reference);
- if (shaderRepo)
- {
- // Add all existing shaders from modules to the new shader repository.
- // If the shader repository is registered in a modules activator, the
- // GetLoadedModules() function call below will also return the module
- // which is currently registering the repository. The HandleModuleEvent
- // method contains code to avoid double registrations due to a fired
- // ModuleEvent::LOADED event after the activators Load() method finished.
- std::vector modules = us::ModuleRegistry::GetLoadedModules();
- for (std::vector::const_iterator iter = modules.begin(),
- endIter = modules.end(); iter != endIter; ++iter)
- {
- this->AddModuleShaderToRepository(*iter, shaderRepo);
- }
-
- m_ShaderRepositories.push_back(shaderRepo);
- }
- return shaderRepo;
- }
-
- void RemovedService(const ServiceReferenceType& /*reference*/, TrackedType tracked)
- {
- m_ShaderRepositories.erase(std::remove(m_ShaderRepositories.begin(), m_ShaderRepositories.end(), tracked),
- m_ShaderRepositories.end());
- }
-
- void HandleModuleEvent(const us::ModuleEvent moduleEvent)
- {
- if (moduleEvent.GetType() == us::ModuleEvent::LOADED)
- {
- std::vector shaderRepos;
- for (std::map > >::const_iterator shaderMapIter = m_ModuleIdToShaderIds.begin(),
- shaderMapEndIter = m_ModuleIdToShaderIds.end(); shaderMapIter != shaderMapEndIter; ++shaderMapIter)
- {
- if (shaderMapIter->second.find(moduleEvent.GetModule()->GetModuleId()) == shaderMapIter->second.end())
- {
- shaderRepos.push_back(shaderMapIter->first);
- }
- }
- AddModuleShadersToRepositories(moduleEvent.GetModule(), shaderRepos);
- }
- else if (moduleEvent.GetType() == us::ModuleEvent::UNLOADED)
- {
- RemoveModuleShadersFromRepositories(moduleEvent.GetModule(), m_ShaderRepositories);
- }
- }
-
- void AddModuleShadersToRepositories(us::Module* module, const std::vector& shaderRepos)
- {
- // search and load shader files
- std::vector shaderResources = module->FindResources("Shaders", "*.xml", true);
- for (std::vector::iterator i = shaderResources.begin();
- i != shaderResources.end(); ++i)
- {
- if (*i)
- {
- us::ModuleResourceStream rs(*i);
- for (std::vector::const_iterator shaderRepoIter = shaderRepos.begin(),
- shaderRepoEndIter = shaderRepos.end(); shaderRepoIter != shaderRepoEndIter; ++shaderRepoIter)
- {
- int id = (*shaderRepoIter)->LoadShader(rs, i->GetBaseName());
- if (id >= 0)
- {
- m_ModuleIdToShaderIds[*shaderRepoIter][module->GetModuleId()].push_back(id);
- }
- }
- rs.seekg(0, std::ios_base::beg);
- }
- }
- }
-
- void AddModuleShaderToRepository(us::Module* module, mitk::IShaderRepository* shaderRepo)
- {
- std::vector shaderRepos;
- shaderRepos.push_back(shaderRepo);
- this->AddModuleShadersToRepositories(module, shaderRepos);
- }
-
- void RemoveModuleShadersFromRepositories(us::Module* module,
- const std::vector& shaderRepos)
- {
- for (std::vector::const_iterator shaderRepoIter = shaderRepos.begin(),
- shaderRepoEndIter = shaderRepos.end(); shaderRepoIter != shaderRepoEndIter; ++shaderRepoIter)
- {
- std::map >& moduleIdToShaderIds = m_ModuleIdToShaderIds[*shaderRepoIter];
- std::map >::iterator shaderIdsIter =
- moduleIdToShaderIds.find(module->GetModuleId());
- if (shaderIdsIter != moduleIdToShaderIds.end())
- {
- for (std::vector::iterator idIter = shaderIdsIter->second.begin();
- idIter != shaderIdsIter->second.end(); ++idIter)
- {
- (*shaderRepoIter)->UnloadShader(*idIter);
- }
- moduleIdToShaderIds.erase(shaderIdsIter);
- }
- }
- }
-
-private:
-
- // Maps to each shader repository a map containing module ids and related
- // shader registration ids
- std::map > > m_ModuleIdToShaderIds;
- std::vector m_ShaderRepositories;
-};
-
-/*
- * This is the module activator for the "Mitk" module. It registers core services
- * like ...
- */
-class MitkCoreActivator : public us::ModuleActivator
-{
-public:
-
- void Load(us::ModuleContext* context)
- {
- // Handle messages from CppMicroServices
- us::installMsgHandler(HandleMicroServicesMessages);
-
- // Add the current application directory to the auto-load paths.
- // This is useful for third-party executables.
- std::string programPath = mitk::IOUtil::GetProgramPath();
- if (programPath.empty())
- {
- MITK_WARN << "Could not get the program path.";
- }
- else
- {
- AddMitkAutoLoadPaths(programPath);
- }
-
- //m_RenderingManager = mitk::RenderingManager::New();
- //context->RegisterService(renderingManager.GetPointer());
- m_PlanePositionManager.reset(new mitk::PlanePositionManagerService);
- context->RegisterService(m_PlanePositionManager.get());
-
- m_CoreDataNodeReader.reset(new mitk::CoreDataNodeReader);
- context->RegisterService(m_CoreDataNodeReader.get());
-
- m_PropertyAliases.reset(new mitk::PropertyAliases);
- context->RegisterService(m_PropertyAliases.get());
-
- m_PropertyDescriptions.reset(new mitk::PropertyDescriptions);
- context->RegisterService(m_PropertyDescriptions.get());
-
- m_PropertyExtensions.reset(new mitk::PropertyExtensions);
- context->RegisterService(m_PropertyExtensions.get());
-
- m_PropertyFilters.reset(new mitk::PropertyFilters);
- context->RegisterService(m_PropertyFilters.get());
-
- m_ShaderRepositoryTracker.Open();
-
- /*
- There IS an option to exchange ALL vtkTexture instances against vtkNeverTranslucentTextureFactory.
- This code is left here as a reminder, just in case we might need to do that some time.
-
- vtkNeverTranslucentTextureFactory* textureFactory = vtkNeverTranslucentTextureFactory::New();
- vtkObjectFactory::RegisterFactory( textureFactory );
- textureFactory->Delete();
- */
- }
-
- void Unload(us::ModuleContext* )
- {
- // The mitk::ModuleContext* argument of the Unload() method
- // will always be 0 for the Mitk library. It makes no sense
- // to use it at this stage anyway, since all libraries which
- // know about the module system have already been unloaded.
-
- m_ShaderRepositoryTracker.Close();
- }
-
-private:
-
- ShaderRepositoryTracker m_ShaderRepositoryTracker;
-
- //mitk::RenderingManager::Pointer m_RenderingManager;
- std::auto_ptr m_PlanePositionManager;
- std::auto_ptr m_CoreDataNodeReader;
- std::auto_ptr m_PropertyAliases;
- std::auto_ptr m_PropertyDescriptions;
- std::auto_ptr m_PropertyExtensions;
- std::auto_ptr m_PropertyFilters;
-};
-
-US_EXPORT_MODULE_ACTIVATOR(MitkCore, MitkCoreActivator)
-
-// Call CppMicroservices initialization code at the end of the file.
-// This especially ensures that VTK object factories have already
-// been registered (VTK initialization code is injected by implicitly
-// include VTK header files at the top of this file).
-US_INITIALIZE_MODULE("MitkCore", "MitkCore")
diff --git a/Core/Code/Controllers/mitkPlanePositionManager.h b/Core/Code/Controllers/mitkPlanePositionManager.h
index cddb1e9f95..9c71be65fb 100644
--- a/Core/Code/Controllers/mitkPlanePositionManager.h
+++ b/Core/Code/Controllers/mitkPlanePositionManager.h
@@ -1,94 +1,94 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
Copyright (c) German Cancer Research Center,
Division of Medical and Biological Informatics.
All rights reserved.
This software is distributed WITHOUT ANY WARRANTY; without
even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE.
See LICENSE.txt or http://www.mitk.org for details.
===================================================================*/
#ifndef mitkPlanePositionManager_h_Included
#define mitkPlanePositionManager_h_Included
#include "mitkCommon.h"
#include "mitkRestorePlanePositionOperation.h"
#include "mitkDataStorage.h"
-#include
+#include
#include
class MitkCoreActivator;
namespace mitk
{
/**
The mitk::PlanePositionManagerService holds and manages a list of certain planepositions.
To store a new position you need to specify the first slice of your slicestack and the
slicenumber you want to restore in the mitk::PlanePositionManager::AddNewPlanePosition() function.
To restore a position call mitk::PlanePositionManagerService::GetPlanePosition(ID) where ID is the position
in the plane positionlist (returned by AddNewPlanePostion). This will give a mitk::RestorePlanePositionOperation
which can be executed by the SliceNavigationController of the slicestack.
\sa QmitkSegmentationView.cpp
*/
class MITK_CORE_EXPORT PlanePositionManagerService
{
public:
PlanePositionManagerService();
~PlanePositionManagerService();
/**
\brief Adds a new plane position to the list. If this geometry is identical to one of the list nothing will be added
\a plane THE FIRST! slice of the slice stack
\a sliceIndex the slice number of the selected slice
\return returns the ID i.e. the position in the positionlist. If the PlaneGeometry which is to be added already exists the existing
ID will be returned.
*/
unsigned int AddNewPlanePosition(const mitk::PlaneGeometry* plane, unsigned int sliceIndex = 0);
/**
\brief Removes the plane at the position \a ID from the list.
\a ID the plane ID which should be removed, i.e. its position in the list
\return true if the plane was removed successfully and false if it is an invalid ID
*/
bool RemovePlanePosition(unsigned int ID);
/// \brief Clears the complete positionlist
void RemoveAllPlanePositions();
/**
\brief Getter for a specific plane position with a given ID
\a ID the ID of the plane position
\return Returns a RestorePlanePositionOperation which can be executed by th SliceNavigationController or NULL for an invalid ID
*/
mitk::RestorePlanePositionOperation* GetPlanePosition( unsigned int ID);
/// \brief Getting the number of all stored planes
unsigned int GetNumberOfPlanePositions();
private:
// Disable copy constructor and assignment operator.
PlanePositionManagerService(const PlanePositionManagerService&);
PlanePositionManagerService& operator=(const PlanePositionManagerService&);
std::vector m_PositionList;
};
}
-US_DECLARE_SERVICE_INTERFACE(mitk::PlanePositionManagerService, "org.mitk.PlanePositionManagerService")
+MITK_DECLARE_SERVICE_INTERFACE(mitk::PlanePositionManagerService, "org.mitk.PlanePositionManagerService")
#endif
diff --git a/Core/Code/IO/mitkAbstractFileIO.cpp b/Core/Code/IO/mitkAbstractFileIO.cpp
index 0789b88c60..4fd52a6613 100644
--- a/Core/Code/IO/mitkAbstractFileIO.cpp
+++ b/Core/Code/IO/mitkAbstractFileIO.cpp
@@ -1,193 +1,194 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
Copyright (c) German Cancer Research Center,
Division of Medical and Biological Informatics.
All rights reserved.
This software is distributed WITHOUT ANY WARRANTY; without
even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE.
See LICENSE.txt or http://www.mitk.org for details.
===================================================================*/
#include "mitkAbstractFileIO.h"
#include "mitkCustomMimeType.h"
namespace mitk {
AbstractFileIO::Options AbstractFileIO::GetReaderOptions() const
{
return AbstractFileReader::GetOptions();
}
us::Any AbstractFileIO::GetReaderOption(const std::string& name) const
{
return AbstractFileReader::GetOption(name);
}
void AbstractFileIO::SetReaderOptions(const AbstractFileIO::Options& options)
{
AbstractFileReader::SetOptions(options);
}
void AbstractFileIO::SetReaderOption(const std::string& name, const us::Any& value)
{
AbstractFileReader::SetOption(name, value);
}
AbstractFileIO::Options AbstractFileIO::GetWriterOptions() const
{
return AbstractFileWriter::GetOptions();
}
us::Any AbstractFileIO::GetWriterOption(const std::string& name) const
{
return AbstractFileWriter::GetOption(name);
}
void AbstractFileIO::SetWriterOptions(const AbstractFileIO::Options& options)
{
AbstractFileWriter::SetOptions(options);
}
void AbstractFileIO::SetWriterOption(const std::string& name, const us::Any& value)
{
AbstractFileWriter::SetOption(name, value);
}
IFileIO::ConfidenceLevel AbstractFileIO::GetReaderConfidenceLevel() const
{
return AbstractFileIOReader::GetReaderConfidenceLevel();
}
IFileIO::ConfidenceLevel AbstractFileIO::GetWriterConfidenceLevel() const
{
return AbstractFileIOWriter::GetWriterConfidenceLevel();
}
std::pair, us::ServiceRegistration >
AbstractFileIO::RegisterService(us::ModuleContext* context)
{
std::pair, us::ServiceRegistration > result;
result.first = this->AbstractFileReader::RegisterService(context);
- CustomMimeType writerMimeType = this->AbstractFileWriter::GetMimeType();
- if (writerMimeType.GetName().empty() && writerMimeType.GetExtensions().empty())
+ const CustomMimeType* writerMimeType = this->AbstractFileWriter::GetMimeType();
+ if (writerMimeType == NULL ||
+ (writerMimeType->GetName().empty() && writerMimeType->GetExtensions().empty()))
{
this->AbstractFileWriter::SetMimeType(CustomMimeType(this->AbstractFileReader::GetRegisteredMimeType().GetName()));
}
result.second = this->AbstractFileWriter::RegisterService(context);
return result;
}
AbstractFileIO::AbstractFileIO(const AbstractFileIO& other)
: AbstractFileIOReader(other)
, AbstractFileIOWriter(other)
{
}
AbstractFileIO::AbstractFileIO(const std::string& baseDataType)
: AbstractFileIOReader()
, AbstractFileIOWriter(baseDataType)
{
}
AbstractFileIO::AbstractFileIO(const std::string& baseDataType,
const CustomMimeType& mimeType,
const std::string& description)
: AbstractFileIOReader(mimeType, description)
, AbstractFileIOWriter(baseDataType, CustomMimeType(mimeType.GetName()), description)
{
}
void AbstractFileIO::SetMimeType(const CustomMimeType& mimeType)
{
this->AbstractFileReader::SetMimeType(mimeType);
this->AbstractFileWriter::SetMimeType(CustomMimeType(mimeType.GetName()));
}
-CustomMimeType AbstractFileIO::GetMimeType() const
+const CustomMimeType* AbstractFileIO::GetMimeType() const
{
- CustomMimeType mimeType = this->AbstractFileReader::GetMimeType();
- if (mimeType.GetName() != this->AbstractFileWriter::GetMimeType().GetName())
+ const CustomMimeType* mimeType = this->AbstractFileReader::GetMimeType();
+ if (mimeType->GetName() != this->AbstractFileWriter::GetMimeType()->GetName())
{
MITK_WARN << "Reader and writer mime-tpyes are different, using the mime-type from IFileReader";
}
return mimeType;
}
void AbstractFileIO::SetReaderDescription(const std::string& description)
{
this->AbstractFileReader::SetDescription(description);
}
std::string AbstractFileIO::GetReaderDescription() const
{
return this->AbstractFileReader::GetDescription();
}
void AbstractFileIO::SetWriterDescription(const std::string& description)
{
this->AbstractFileWriter::SetDescription(description);
}
std::string AbstractFileIO::GetWriterDescription() const
{
return this->AbstractFileWriter::GetDescription();
}
void AbstractFileIO::SetDefaultReaderOptions(const AbstractFileIO::Options& defaultOptions)
{
this->AbstractFileReader::SetDefaultOptions(defaultOptions);
}
AbstractFileIO::Options AbstractFileIO::GetDefaultReaderOptions() const
{
return this->AbstractFileReader::GetDefaultOptions();
}
void AbstractFileIO::SetDefaultWriterOptions(const AbstractFileIO::Options& defaultOptions)
{
this->AbstractFileWriter::SetDefaultOptions(defaultOptions);
}
AbstractFileIO::Options AbstractFileIO::GetDefaultWriterOptions() const
{
return this->AbstractFileWriter::GetDefaultOptions();
}
void AbstractFileIO::SetReaderRanking(int ranking)
{
this->AbstractFileReader::SetRanking(ranking);
}
int AbstractFileIO::GetReaderRanking() const
{
return this->AbstractFileReader::GetRanking();
}
void AbstractFileIO::SetWriterRanking(int ranking)
{
this->AbstractFileWriter::SetRanking(ranking);
}
int AbstractFileIO::GetWriterRanking() const
{
return this->AbstractFileWriter::GetRanking();
}
IFileReader* AbstractFileIO::ReaderClone() const
{
return this->IOClone();
}
IFileWriter* AbstractFileIO::WriterClone() const
{
return this->IOClone();
}
}
diff --git a/Core/Code/IO/mitkAbstractFileIO.h b/Core/Code/IO/mitkAbstractFileIO.h
index b66a73dce3..3791432ac0 100644
--- a/Core/Code/IO/mitkAbstractFileIO.h
+++ b/Core/Code/IO/mitkAbstractFileIO.h
@@ -1,192 +1,192 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
Copyright (c) German Cancer Research Center,
Division of Medical and Biological Informatics.
All rights reserved.
This software is distributed WITHOUT ANY WARRANTY; without
even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE.
See LICENSE.txt or http://www.mitk.org for details.
===================================================================*/
#ifndef MITKABSTRACTFILEIO_H
#define MITKABSTRACTFILEIO_H
#include "mitkAbstractFileReader.h"
#include "mitkAbstractFileWriter.h"
namespace mitk {
#ifndef DOXYGEN_SKIP
// Skip this code during Doxygen processing, because it only
// exists to resolve name clashes when inheriting from both
// AbstractFileReader and AbstractFileWriter.
class AbstractFileIOReader : public AbstractFileReader
{
public:
virtual ConfidenceLevel GetReaderConfidenceLevel() const
{
return AbstractFileReader::GetConfidenceLevel();
}
virtual ConfidenceLevel GetConfidenceLevel() const
{
return this->GetReaderConfidenceLevel();
}
protected:
AbstractFileIOReader() {}
AbstractFileIOReader(const CustomMimeType& mimeType, const std::string& description)
: AbstractFileReader(mimeType, description) {}
private:
virtual IFileReader* ReaderClone() const = 0;
IFileReader* Clone() const { return ReaderClone(); }
};
struct AbstractFileIOWriter : public AbstractFileWriter
{
virtual ConfidenceLevel GetWriterConfidenceLevel() const
{
return AbstractFileWriter::GetConfidenceLevel();
}
virtual ConfidenceLevel GetConfidenceLevel() const
{
return this->GetWriterConfidenceLevel();
}
protected:
AbstractFileIOWriter(const std::string& baseDataType) : AbstractFileWriter(baseDataType) {}
AbstractFileIOWriter(const std::string& baseDataType, const CustomMimeType& mimeType,
const std::string& description)
: AbstractFileWriter(baseDataType, mimeType, description) {}
private:
virtual IFileWriter* WriterClone() const = 0;
IFileWriter* Clone() const { return WriterClone(); }
};
#endif // DOXYGEN_SKIP
class MITK_CORE_EXPORT AbstractFileIO : public AbstractFileIOReader, public AbstractFileIOWriter
{
public:
Options GetReaderOptions() const;
us::Any GetReaderOption(const std::string &name) const;
void SetReaderOptions(const Options& options);
void SetReaderOption(const std::string& name, const us::Any& value);
Options GetWriterOptions() const;
us::Any GetWriterOption(const std::string &name) const;
void SetWriterOptions(const Options& options);
void SetWriterOption(const std::string& name, const us::Any& value);
virtual ConfidenceLevel GetReaderConfidenceLevel() const;
virtual ConfidenceLevel GetWriterConfidenceLevel() const;
std::pair, us::ServiceRegistration >
RegisterService(us::ModuleContext* context = us::GetModuleContext());
protected:
AbstractFileIO(const AbstractFileIO& other);
AbstractFileIO(const std::string& baseDataType);
/**
* Associate this reader instance with the given MIME type.
*
* @param mimeType The mime type this reader can read.
* @param description A human readable description of this reader.
*
* @throws std::invalid_argument if \c mimeType is empty.
*
* @see RegisterService
*/
explicit AbstractFileIO(const std::string& baseDataType, const CustomMimeType& mimeType,
const std::string& description);
/**
* Associate this reader with the given file extension.
*
* Additonal file extensions can be added by sub-classes by calling AddExtension
* or SetExtensions on the CustomMimeType object returned by GetMimeType() and
* setting the modified object again via SetMimeType().
*
* @param extension The file extension (without a leading period) for which a registered
* mime-type object is looked up and associated with this instance.
* @param description A human readable description of this reader.
*
* @see RegisterService
*/
explicit AbstractFileIO(const std::string& baseDataType, const std::string& extension,
const std::string& description);
void SetMimeType(const CustomMimeType& mimeType);
/**
* @return The mime-type this reader can handle.
*/
- CustomMimeType GetMimeType() const;
+ const CustomMimeType* GetMimeType() const;
void SetReaderDescription(const std::string& description);
std::string GetReaderDescription() const;
void SetWriterDescription(const std::string& description);
std::string GetWriterDescription() const;
void SetDefaultReaderOptions(const Options& defaultOptions);
Options GetDefaultReaderOptions() const;
void SetDefaultWriterOptions(const Options& defaultOptions);
Options GetDefaultWriterOptions() const;
/**
* \brief Set the service ranking for this file reader.
*
* Default is zero and should only be chosen differently for a reason.
* The ranking is used to determine which reader to use if several
* equivalent readers have been found.
* It may be used to replace a default reader from MITK in your own project.
* E.g. if you want to use your own reader for nrrd files instead of the default,
* implement it and give it a higher ranking than zero.
*/
void SetReaderRanking(int ranking);
int GetReaderRanking() const;
void SetWriterRanking(int ranking);
int GetWriterRanking() const;
private:
AbstractFileIO& operator=(const AbstractFileIO& other);
virtual AbstractFileIO* IOClone() const = 0;
virtual IFileReader* ReaderClone() const;
virtual IFileWriter* WriterClone() const;
};
}
#endif // MITKABSTRACTFILEIO_H
diff --git a/Core/Code/IO/mitkAbstractFileReader.cpp b/Core/Code/IO/mitkAbstractFileReader.cpp
index c03e03d3fd..411e83bd99 100644
--- a/Core/Code/IO/mitkAbstractFileReader.cpp
+++ b/Core/Code/IO/mitkAbstractFileReader.cpp
@@ -1,399 +1,414 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
Copyright (c) German Cancer Research Center,
Division of Medical and Biological Informatics.
All rights reserved.
This software is distributed WITHOUT ANY WARRANTY; without
even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE.
See LICENSE.txt or http://www.mitk.org for details.
===================================================================*/
#include
#include
#include
+#include
#include
#include
#include
#include
#include
#include
namespace mitk {
AbstractFileReader::InputStream::InputStream(IFileReader* reader, std::ios_base::openmode mode)
: std::istream(NULL)
, m_Stream(NULL)
{
std::istream* stream = reader->GetInputStream();
if (stream)
{
this->init(stream->rdbuf());
}
else
{
m_Stream = new std::ifstream(reader->GetInputLocation().c_str(), mode);
this->init(m_Stream->rdbuf());
}
}
AbstractFileReader::InputStream::~InputStream()
{
delete m_Stream;
}
class AbstractFileReader::Impl : public FileReaderWriterBase
{
public:
Impl()
: FileReaderWriterBase()
, m_Stream(NULL)
, m_PrototypeFactory(NULL)
{}
Impl(const Impl& other)
: FileReaderWriterBase(other)
, m_Stream(NULL)
, m_PrototypeFactory(NULL)
{}
std::string m_Location;
std::string m_TmpFile;
std::istream* m_Stream;
us::PrototypeServiceFactory* m_PrototypeFactory;
us::ServiceRegistration m_Reg;
};
AbstractFileReader::AbstractFileReader()
: d(new Impl)
{
}
AbstractFileReader::~AbstractFileReader()
{
UnregisterService();
delete d->m_PrototypeFactory;
if (!d->m_TmpFile.empty())
{
std::remove(d->m_TmpFile.c_str());
}
}
AbstractFileReader::AbstractFileReader(const AbstractFileReader& other)
: IFileReader(),
d(new Impl(*other.d.get()))
-
{
}
AbstractFileReader::AbstractFileReader(const CustomMimeType& mimeType, const std::string& description)
: d(new Impl)
{
d->SetMimeType(mimeType);
d->SetDescription(description);
}
////////////////////// Reading /////////////////////////
+std::vector AbstractFileReader::Read()
+{
+ std::vector result;
+
+ DataStorage::Pointer ds = StandaloneDataStorage::New().GetPointer();
+ this->Read(*ds);
+ DataStorage::SetOfObjects::ConstPointer dataNodes = ds->GetAll();
+ for (DataStorage::SetOfObjects::ConstIterator iter = dataNodes->Begin(),
+ iterEnd = dataNodes->End(); iter != iterEnd; ++iter)
+ {
+ result.push_back(iter.Value()->GetData());
+ }
+ return result;
+}
+
DataStorage::SetOfObjects::Pointer AbstractFileReader::Read(DataStorage& ds)
{
DataStorage::SetOfObjects::Pointer result = DataStorage::SetOfObjects::New();
std::vector data = this->Read();
for (std::vector::iterator iter = data.begin();
iter != data.end(); ++iter)
{
mitk::DataNode::Pointer node = mitk::DataNode::New();
node->SetData(*iter);
this->SetDefaultDataNodeProperties(node, this->GetInputLocation());
ds.Add(node);
result->InsertElement(result->Size(), node);
}
return result;
}
IFileReader::ConfidenceLevel AbstractFileReader::GetConfidenceLevel() const
{
if (d->m_Stream)
{
if (*d->m_Stream) return Supported;
}
else
{
if (itksys::SystemTools::FileExists(this->GetInputLocation().c_str(), true))
{
return Supported;
}
}
return Unsupported;
}
//////////// µS Registration & Properties //////////////
us::ServiceRegistration AbstractFileReader::RegisterService(us::ModuleContext* context)
{
if (d->m_PrototypeFactory) return us::ServiceRegistration();
if(context == NULL)
{
context = us::GetModuleContext();
}
d->RegisterMimeType(context);
- if (this->GetMimeType().GetName().empty())
+ if (this->GetMimeType()->GetName().empty())
{
MITK_WARN << "Not registering reader due to empty MIME type.";
return us::ServiceRegistration();
}
struct PrototypeFactory : public us::PrototypeServiceFactory
{
AbstractFileReader* const m_Prototype;
PrototypeFactory(AbstractFileReader* prototype)
: m_Prototype(prototype)
{}
us::InterfaceMap GetService(us::Module* /*module*/, const us::ServiceRegistrationBase& /*registration*/)
{
return us::MakeInterfaceMap(m_Prototype->Clone());
}
void UngetService(us::Module* /*module*/, const us::ServiceRegistrationBase& /*registration*/,
const us::InterfaceMap& service)
{
delete us::ExtractInterface(service);
}
};
d->m_PrototypeFactory = new PrototypeFactory(this);
us::ServiceProperties props = this->GetServiceProperties();
d->m_Reg = context->RegisterService(d->m_PrototypeFactory, props);
return d->m_Reg;
}
void AbstractFileReader::UnregisterService()
{
try
{
d->m_Reg.Unregister();
}
catch (const std::exception&)
{}
}
us::ServiceProperties AbstractFileReader::GetServiceProperties() const
{
us::ServiceProperties result;
result[IFileReader::PROP_DESCRIPTION()] = this->GetDescription();
- result[IFileReader::PROP_MIMETYPE()] = this->GetMimeType().GetName();
+ result[IFileReader::PROP_MIMETYPE()] = this->GetMimeType()->GetName();
result[us::ServiceConstants::SERVICE_RANKING()] = this->GetRanking();
return result;
}
us::ServiceRegistration AbstractFileReader::RegisterMimeType(us::ModuleContext* context)
{
return d->RegisterMimeType(context);
}
void AbstractFileReader::SetMimeType(const CustomMimeType& mimeType)
{
d->SetMimeType(mimeType);
}
void AbstractFileReader::SetDescription(const std::string& description)
{
d->SetDescription(description);
}
void AbstractFileReader::SetRanking(int ranking)
{
d->SetRanking(ranking);
}
int AbstractFileReader::GetRanking() const
{
return d->GetRanking();
}
std::string AbstractFileReader::GetLocalFileName() const
{
std::string localFileName;
if (d->m_Stream)
{
if (d->m_TmpFile.empty())
{
// write the stream contents to temporary file
std::string ext = itksys::SystemTools::GetFilenameExtension(this->GetInputLocation());
std::ofstream tmpStream;
localFileName = mitk::IOUtil::CreateTemporaryFile(tmpStream, std::ios_base::out | std::ios_base::trunc | std::ios_base::binary,
"XXXXXX" + ext);
tmpStream << d->m_Stream->rdbuf();
d->m_TmpFile = localFileName;
}
else
{
localFileName = d->m_TmpFile;
}
}
else
{
localFileName = d->m_Location;
}
return localFileName;
}
//////////////////////// Options ///////////////////////
void AbstractFileReader::SetDefaultOptions(const IFileReader::Options& defaultOptions)
{
d->SetDefaultOptions(defaultOptions);
}
IFileReader::Options AbstractFileReader::GetDefaultOptions() const
{
return d->GetDefaultOptions();
}
void AbstractFileReader::SetInput(const std::string& location)
{
d->m_Location = location;
d->m_Stream = NULL;
}
void AbstractFileReader::SetInput(const std::string& location, std::istream* is)
{
if (d->m_Stream != is && !d->m_TmpFile.empty())
{
std::remove(d->m_TmpFile.c_str());
d->m_TmpFile.clear();
}
d->m_Location = location;
d->m_Stream = is;
}
std::string AbstractFileReader::GetInputLocation() const
{
return d->m_Location;
}
std::istream*AbstractFileReader::GetInputStream() const
{
return d->m_Stream;
}
MimeType AbstractFileReader::GetRegisteredMimeType() const
{
return d->GetRegisteredMimeType();
}
IFileReader::Options AbstractFileReader::GetOptions() const
{
return d->GetOptions();
}
us::Any AbstractFileReader::GetOption(const std::string& name) const
{
return d->GetOption(name);
}
void AbstractFileReader::SetOptions(const Options& options)
{
d->SetOptions(options);
}
void AbstractFileReader::SetOption(const std::string& name, const us::Any& value)
{
d->SetOption(name, value);
}
////////////////// MISC //////////////////
void AbstractFileReader::AddProgressCallback(const ProgressCallback& callback)
{
d->AddProgressCallback(callback);
}
void AbstractFileReader::RemoveProgressCallback(const ProgressCallback& callback)
{
d->RemoveProgressCallback(callback);
}
////////////////// µS related Getters //////////////////
-CustomMimeType AbstractFileReader::GetMimeType() const
+const CustomMimeType* AbstractFileReader::GetMimeType() const
{
return d->GetMimeType();
}
void AbstractFileReader::SetMimeTypePrefix(const std::string& prefix)
{
d->SetMimeTypePrefix(prefix);
}
std::string AbstractFileReader::GetMimeTypePrefix() const
{
return d->GetMimeTypePrefix();
}
std::string AbstractFileReader::GetDescription() const
{
return d->GetDescription();
}
void AbstractFileReader::SetDefaultDataNodeProperties(DataNode* node, const std::string& filePath)
{
// path
if (!filePath.empty())
{
mitk::StringProperty::Pointer pathProp = mitk::StringProperty::New( itksys::SystemTools::GetFilenamePath(filePath) );
node->SetProperty(StringProperty::PATH, pathProp);
}
// name already defined?
mitk::StringProperty::Pointer nameProp = dynamic_cast(node->GetProperty("name"));
if(nameProp.IsNull() || (strcmp(nameProp->GetValue(),"No Name!")==0))
{
// name already defined in BaseData
mitk::StringProperty::Pointer baseDataNameProp = dynamic_cast(node->GetData()->GetProperty("name").GetPointer() );
if(baseDataNameProp.IsNull() || (strcmp(baseDataNameProp->GetValue(),"No Name!")==0))
{
// name neither defined in node, nor in BaseData -> name = filebasename;
nameProp = mitk::StringProperty::New(itksys::SystemTools::GetFilenameWithoutExtension(itksys::SystemTools::GetFilenameName(filePath)));
node->SetProperty("name", nameProp);
}
else
{
// name defined in BaseData!
nameProp = mitk::StringProperty::New(baseDataNameProp->GetValue());
node->SetProperty("name", nameProp);
}
}
// visibility
if(!node->GetProperty("visible"))
{
node->SetVisibility(true);
}
}
}
diff --git a/Core/Code/IO/mitkAbstractFileReader.h b/Core/Code/IO/mitkAbstractFileReader.h
index de905aa836..dbcccfa3d3 100644
--- a/Core/Code/IO/mitkAbstractFileReader.h
+++ b/Core/Code/IO/mitkAbstractFileReader.h
@@ -1,231 +1,231 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
Copyright (c) German Cancer Research Center,
Division of Medical and Biological Informatics.
All rights reserved.
This software is distributed WITHOUT ANY WARRANTY; without
even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE.
See LICENSE.txt or http://www.mitk.org for details.
===================================================================*/
#ifndef AbstractFileReader_H_HEADER_INCLUDED_C1E7E521
#define AbstractFileReader_H_HEADER_INCLUDED_C1E7E521
// Macro
#include
// MITK
#include
#include
#include
// Microservices
#include
#include
#include
namespace us {
struct PrototypeServiceFactory;
}
namespace mitk {
class CustomMimeType;
/**
* @brief Base class for creating mitk::BaseData objects from files or streams.
* @ingroup IO
*/
class MITK_CORE_EXPORT AbstractFileReader : public mitk::IFileReader
{
public:
virtual void SetInput(const std::string& location);
virtual void SetInput(const std::string &location, std::istream* is);
virtual std::string GetInputLocation() const;
virtual std::istream* GetInputStream() const;
MimeType GetRegisteredMimeType() const;
/**
* @brief Reads a path or stream and creates a list of BaseData objects.
*
* This method must be implemented for each specific reader. Call
* GetInputStream() first and check for a non-null stream to read from.
* If the input stream is \c NULL, use GetInputLocation() to read from a local
* file-system path.
*
* If the reader cannot use streams directly, use GetLocalFileName() instead.
*
* @return The created BaseData objects.
* @throws mitk::Exception
*
* @see GetLocalFileName()
* @see IFileReader::Read()
*/
virtual std::vector > Read() = 0;
virtual DataStorage::SetOfObjects::Pointer Read(mitk::DataStorage& ds);
virtual ConfidenceLevel GetConfidenceLevel() const;
virtual Options GetOptions() const;
virtual us::Any GetOption(const std::string &name) const;
virtual void SetOptions(const Options& options);
virtual void SetOption(const std::string& name, const us::Any& value);
virtual void AddProgressCallback(const ProgressCallback& callback);
virtual void RemoveProgressCallback(const ProgressCallback& callback);
/**
* Associate this reader with the MIME type returned by the current IMimeTypeProvider
* service for the provided extension if the MIME type exists, otherwise registers
* a new MIME type when RegisterService() is called.
*
* If no MIME type for \c extension is already registered, a call to RegisterService()
* will register a new MIME type and associate this reader instance with it. The MIME
* type id can be set via SetMimeType() or it will be auto-generated using \c extension,
* having the form "application/vnd.mitk.".
*
* @param extension The file extension (without a leading period) for which a registered
* mime-type object is looked up and associated with this reader instance.
* @param description A human readable description of this reader.
*/
us::ServiceRegistration RegisterService(us::ModuleContext* context = us::GetModuleContext());
void UnregisterService();
protected:
/**
* @brief An input stream wrapper.
*
* If a reader can only work with input streams, use an instance
* of this class to either wrap the specified input stream or
* create a new input stream based on the input location in the
* file system.
*/
class InputStream : public std::istream
{
public:
InputStream(IFileReader* writer, std::ios_base::openmode mode = std::ios_base::in);
~InputStream();
private:
std::istream* m_Stream;
};
AbstractFileReader();
~AbstractFileReader();
AbstractFileReader(const AbstractFileReader& other);
/**
* Associate this reader instance with the given MIME type.
*
* If \c mimeType does not provide an extension list, an already
* registered mime-type object is used. Otherwise, the first entry in
* the extensions list is used to construct a mime-type name and
* register it as a new CustomMimeType service object in the default
* implementation of RegisterMimeType().
*
* @param mimeType The mime type this reader can read.
* @param description A human readable description of this reader.
*
* @throws std::invalid_argument if \c mimeType is empty.
*
* @see RegisterService
*/
explicit AbstractFileReader(const CustomMimeType& mimeType, const std::string& description);
virtual us::ServiceProperties GetServiceProperties() const;
/**
* Registers a new CustomMimeType service object.
*
* This method is called from RegisterService and the default implementation
* registers a new mime-type service object if all of the following conditions
* are true:
*
* - TODO
*
* @param context
* @return
* @throws std::invalid_argument if \c context is NULL.
*/
virtual us::ServiceRegistration RegisterMimeType(us::ModuleContext* context);
void SetMimeType(const CustomMimeType& mimeType);
/**
* @return The mime-type this reader can handle.
*/
- CustomMimeType GetMimeType() const;
+ const CustomMimeType* GetMimeType() const;
void SetMimeTypePrefix(const std::string& prefix);
std::string GetMimeTypePrefix() const;
void SetDescription(const std::string& description);
std::string GetDescription() const;
void SetDefaultOptions(const Options& defaultOptions);
Options GetDefaultOptions() const;
/**
* \brief Set the service ranking for this file reader.
*
* Default is zero and should only be chosen differently for a reason.
* The ranking is used to determine which reader to use if several
* equivalent readers have been found.
* It may be used to replace a default reader from MITK in your own project.
* E.g. if you want to use your own reader for nrrd files instead of the default,
* implement it and give it a higher ranking than zero.
*/
void SetRanking(int ranking);
int GetRanking() const;
/**
* @brief Get a local file name for reading.
*
* This is a convenience method for readers which cannot work natively
* with input streams. If no input stream has been been set,
* this method just returns the result of GetLocation(). However, if
* SetLocation(std::string, std::istream*) has been called with a non-null
* input stream, this method writes the contents of the stream to a temporary
* file and returns the name of the temporary file.
*
* The temporary file is deleted when either SetLocation(std::string, std::istream*)
* is called again with a different input stream or the destructor of this
* class is called.
*
* This method does not validate file names set via SetInput(std::string).
*
* @return A file path in the local file-system for reading.
*/
std::string GetLocalFileName() const;
virtual void SetDefaultDataNodeProperties(DataNode* node, const std::string& filePath);
private:
AbstractFileReader& operator=(const AbstractFileReader& other);
virtual mitk::IFileReader* Clone() const = 0;
class Impl;
std::auto_ptr d;
};
} // namespace mitk
#endif /* AbstractFileReader_H_HEADER_INCLUDED_C1E7E521 */
diff --git a/Core/Code/IO/mitkAbstractFileWriter.cpp b/Core/Code/IO/mitkAbstractFileWriter.cpp
index 0fa5c0a066..41b7c5e4df 100644
--- a/Core/Code/IO/mitkAbstractFileWriter.cpp
+++ b/Core/Code/IO/mitkAbstractFileWriter.cpp
@@ -1,395 +1,395 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
Copyright (c) German Cancer Research Center,
Division of Medical and Biological Informatics.
All rights reserved.
This software is distributed WITHOUT ANY WARRANTY; without
even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE.
See LICENSE.txt or http://www.mitk.org for details.
===================================================================*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
namespace mitk {
struct AbstractFileWriter::LocalFile::Impl
{
Impl(const std::string& location, std::ostream* os)
: m_Location(location)
, m_Stream(os)
{}
std::string m_Location;
std::string m_TmpFileName;
std::ostream* m_Stream;
};
AbstractFileWriter::LocalFile::LocalFile(IFileWriter *writer)
: d(new Impl(writer->GetOutputLocation(), writer->GetOutputStream()))
{
}
AbstractFileWriter::LocalFile::~LocalFile()
{
if (d->m_Stream && !d->m_TmpFileName.empty())
{
std::ifstream ifs(d->m_TmpFileName.c_str(), std::ios_base::binary);
*d->m_Stream << ifs.rdbuf();
d->m_Stream->flush();
ifs.close();
std::remove(d->m_TmpFileName.c_str());
}
}
std::string AbstractFileWriter::LocalFile::GetFileName()
{
if (d->m_Stream == NULL)
{
return d->m_Location;
}
else if (d->m_TmpFileName.empty())
{
std::string ext = itksys::SystemTools::GetFilenameExtension(d->m_Location);
d->m_TmpFileName = IOUtil::CreateTemporaryFile("XXXXXX" + ext);
}
return d->m_TmpFileName;
}
AbstractFileWriter::OutputStream::OutputStream(IFileWriter* writer, std::ios_base::openmode mode)
: std::ostream(NULL)
, m_Stream(NULL)
{
std::ostream* stream = writer->GetOutputStream();
if (stream)
{
this->init(stream->rdbuf());
}
else
{
m_Stream = new std::ofstream(writer->GetOutputLocation().c_str(), mode);
this->init(m_Stream->rdbuf());
}
}
AbstractFileWriter::OutputStream::~OutputStream()
{
delete m_Stream;
}
class AbstractFileWriter::Impl : public FileReaderWriterBase
{
public:
Impl()
: FileReaderWriterBase()
, m_BaseData(NULL)
, m_Stream(NULL)
, m_PrototypeFactory(NULL)
{}
Impl(const Impl& other)
: FileReaderWriterBase(other)
, m_BaseDataType(other.m_BaseDataType)
, m_BaseData(NULL)
, m_Stream(NULL)
, m_PrototypeFactory(NULL)
{}
std::string m_BaseDataType;
const BaseData* m_BaseData;
std::string m_Location;
std::ostream* m_Stream;
us::PrototypeServiceFactory* m_PrototypeFactory;
us::ServiceRegistration m_Reg;
};
void AbstractFileWriter::SetInput(const BaseData* data)
{
d->m_BaseData = data;
}
const BaseData* AbstractFileWriter::GetInput() const
{
return d->m_BaseData;
}
void AbstractFileWriter::SetOutputLocation(const std::string& location)
{
d->m_Location = location;
d->m_Stream = NULL;
}
std::string AbstractFileWriter::GetOutputLocation() const
{
return d->m_Location;
}
void AbstractFileWriter::SetOutputStream(const std::string& location, std::ostream* os)
{
d->m_Location = location;
d->m_Stream = os;
}
std::ostream* AbstractFileWriter::GetOutputStream() const
{
return d->m_Stream;
}
AbstractFileWriter::~AbstractFileWriter()
{
UnregisterService();
delete d->m_PrototypeFactory;
}
AbstractFileWriter::AbstractFileWriter(const AbstractFileWriter& other)
: IFileWriter(),
d(new Impl(*other.d.get()))
{
}
AbstractFileWriter::AbstractFileWriter(const std::string& baseDataType)
: d(new Impl)
{
d->m_BaseDataType = baseDataType;
}
AbstractFileWriter::AbstractFileWriter(const std::string& baseDataType, const CustomMimeType& mimeType,
const std::string& description)
: d(new Impl)
{
d->m_BaseDataType = baseDataType;
d->SetMimeType(mimeType);
d->SetDescription(description);
}
////////////////////// Writing /////////////////////////
IFileWriter::ConfidenceLevel AbstractFileWriter::GetConfidenceLevel() const
{
if (d->m_BaseData == NULL) return Unsupported;
std::vector classHierarchy = d->m_BaseData->GetClassHierarchy();
if (std::find(classHierarchy.begin(), classHierarchy.end(), d->m_BaseDataType) ==
classHierarchy.end())
{
return Unsupported;
}
return Supported;
}
MimeType AbstractFileWriter::GetRegisteredMimeType() const
{
return d->GetRegisteredMimeType();
}
//////////// µS Registration & Properties //////////////
us::ServiceRegistration AbstractFileWriter::RegisterService(us::ModuleContext* context)
{
if (d->m_PrototypeFactory) return us::ServiceRegistration();
if(context == NULL)
{
context = us::GetModuleContext();
}
d->RegisterMimeType(context);
- if (this->GetMimeType().GetName().empty())
+ if (this->GetMimeType()->GetName().empty())
{
MITK_WARN << "Not registering writer due to empty MIME type.";
return us::ServiceRegistration();
}
struct PrototypeFactory : public us::PrototypeServiceFactory
{
AbstractFileWriter* const m_Prototype;
PrototypeFactory(AbstractFileWriter* prototype)
: m_Prototype(prototype)
{}
us::InterfaceMap GetService(us::Module* /*module*/, const us::ServiceRegistrationBase& /*registration*/)
{
return us::MakeInterfaceMap(m_Prototype->Clone());
}
void UngetService(us::Module* /*module*/, const us::ServiceRegistrationBase& /*registration*/,
const us::InterfaceMap& service)
{
delete us::ExtractInterface(service);
}
};
d->m_PrototypeFactory = new PrototypeFactory(this);
us::ServiceProperties props = this->GetServiceProperties();
d->m_Reg = context->RegisterService(d->m_PrototypeFactory, props);
return d->m_Reg;
}
void AbstractFileWriter::UnregisterService()
{
try
{
d->m_Reg.Unregister();
}
catch (const std::exception&)
{}
}
us::ServiceProperties AbstractFileWriter::GetServiceProperties() const
{
us::ServiceProperties result;
result[IFileWriter::PROP_DESCRIPTION()] = this->GetDescription();
- result[IFileWriter::PROP_MIMETYPE()] = this->GetMimeType().GetName();
+ result[IFileWriter::PROP_MIMETYPE()] = this->GetMimeType()->GetName();
result[IFileWriter::PROP_BASEDATA_TYPE()] = d->m_BaseDataType;
result[us::ServiceConstants::SERVICE_RANKING()] = this->GetRanking();
// for (IFileWriter::OptionList::const_iterator it = d->m_Options.begin(); it != d->m_Options.end(); ++it)
// {
// result[it->first] = std::string("true");
// }
return result;
}
-CustomMimeType AbstractFileWriter::GetMimeType() const
+const CustomMimeType* AbstractFileWriter::GetMimeType() const
{
return d->GetMimeType();
}
void AbstractFileWriter::SetMimeTypePrefix(const std::string& prefix)
{
d->SetMimeTypePrefix(prefix);
}
std::string AbstractFileWriter::GetMimeTypePrefix() const
{
return d->GetMimeTypePrefix();
}
us::ServiceRegistration AbstractFileWriter::RegisterMimeType(us::ModuleContext* context)
{
return d->RegisterMimeType(context);
}
void AbstractFileWriter::SetMimeType(const CustomMimeType& mimeType)
{
d->SetMimeType(mimeType);
}
void AbstractFileWriter::SetRanking(int ranking)
{
d->SetRanking(ranking);
}
//////////////////////// Options ///////////////////////
void AbstractFileWriter::SetDefaultOptions(const IFileWriter::Options& defaultOptions)
{
d->SetDefaultOptions(defaultOptions);
}
IFileWriter::Options AbstractFileWriter::GetDefaultOptions() const
{
return d->GetDefaultOptions();
}
IFileWriter::Options AbstractFileWriter::GetOptions() const
{
return d->GetOptions();
}
us::Any AbstractFileWriter::GetOption(const std::string& name) const
{
return d->GetOption(name);
}
void AbstractFileWriter::SetOption(const std::string& name, const us::Any& value)
{
d->SetOption(name, value);
}
void AbstractFileWriter::SetOptions(const Options& options)
{
d->SetOptions(options);
}
////////////////// MISC //////////////////
void AbstractFileWriter::AddProgressCallback(const ProgressCallback& callback)
{
d->AddProgressCallback(callback);
}
void AbstractFileWriter::RemoveProgressCallback(const ProgressCallback& callback)
{
d->RemoveProgressCallback(callback);
}
////////////////// µS related Getters //////////////////
int AbstractFileWriter::GetRanking() const
{
return d->GetRanking();
}
void AbstractFileWriter::SetBaseDataType(const std::string& baseDataType)
{
d->m_BaseDataType = baseDataType;
}
std::string AbstractFileWriter::GetDescription() const
{
return d->GetDescription();
}
std::string AbstractFileWriter::GetBaseDataType() const
{
return d->m_BaseDataType;
}
void AbstractFileWriter::ValidateOutputLocation() const
{
if (this->GetOutputStream() == NULL)
{
// check if a file name is set and if we can write to it
const std::string fileName = this->GetOutputLocation();
if (fileName.empty())
{
mitkThrow() << "No output location or stream specified";
}
}
}
void AbstractFileWriter::SetDescription(const std::string& description)
{
d->SetDescription(description);
}
}
diff --git a/Core/Code/IO/mitkAbstractFileWriter.h b/Core/Code/IO/mitkAbstractFileWriter.h
index a9620eff97..9cbcb55568 100644
--- a/Core/Code/IO/mitkAbstractFileWriter.h
+++ b/Core/Code/IO/mitkAbstractFileWriter.h
@@ -1,232 +1,232 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
Copyright (c) German Cancer Research Center,
Division of Medical and Biological Informatics.
All rights reserved.
This software is distributed WITHOUT ANY WARRANTY; without
even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE.
See LICENSE.txt or http://www.mitk.org for details.
===================================================================*/
#ifndef AbstractFileWriter_H_HEADER_INCLUDED_C1E7E521
#define AbstractFileWriter_H_HEADER_INCLUDED_C1E7E521
// Macro
#include
// MITK
#include
#include
// Microservices
#include
#include
#include
#include
namespace us {
struct PrototypeServiceFactory;
}
namespace mitk {
class CustomMimeType;
/**
* @brief Base class for writing mitk::BaseData objects to files or streams.
*
* In general, all file writers should derive from this class, this way it is
* made sure that the new implementation is
* exposed to the Microservice-Framework and that is automatically available troughout MITK.
* The default implementation only requires one Write()
* method and the Clone() method to be implemented.
*
* @ingroup IO
*/
class MITK_CORE_EXPORT AbstractFileWriter : public mitk::IFileWriter
{
public:
virtual void SetInput(const BaseData* data);
virtual const BaseData* GetInput() const;
virtual void SetOutputLocation(const std::string& location);
virtual std::string GetOutputLocation() const;
virtual void SetOutputStream(const std::string& location, std::ostream* os);
virtual std::ostream* GetOutputStream() const;
/**
* \brief Write the base data to the specified location or output stream.
*
* This method must be implemented for each specific writer. Call
* GetOutputStream() first and check for a non-null stream to write to.
* If the output stream is \c NULL, use GetOutputLocation() to write
* to a local file-system path.
*
* If the reader cannot use streams directly, use GetLocalFile() to retrieve
* a temporary local file name instead.
*
* \throws mitk::Exception
*
* \see GetLocalFile()
* \see IFileWriter::Write()
*/
virtual void Write() = 0;
virtual ConfidenceLevel GetConfidenceLevel() const;
MimeType GetRegisteredMimeType() const;
virtual Options GetOptions() const;
virtual us::Any GetOption(const std::string &name) const;
virtual void SetOptions(const Options& options);
virtual void SetOption(const std::string& name, const us::Any& value);
virtual void AddProgressCallback(const ProgressCallback& callback);
virtual void RemoveProgressCallback(const ProgressCallback& callback);
us::ServiceRegistration RegisterService(us::ModuleContext* context = us::GetModuleContext());
void UnregisterService();
protected:
/**
* @brief A local file representation for streams.
*
* If a writer can only work with local files, use an instance
* of this class to get either a temporary file name for writing
* to the specified output stream or the original output location
* if no output stream was set.
*/
class LocalFile
{
public:
LocalFile(IFileWriter* writer);
// Writes to the ostream and removes the temporary file
~LocalFile();
// Creates a temporary file for output operations.
std::string GetFileName();
private:
// disabled
LocalFile();
LocalFile(const LocalFile&);
LocalFile& operator=(const LocalFile& other);
struct Impl;
std::auto_ptr d;
};
/**
* @brief An output stream wrapper.
*
* If a writer can only work with output streams, use an instance
* of this class to either wrap the specified output stream or
* create a new output stream based on the output location in the
* file system.
*/
class OutputStream : public std::ostream
{
public:
OutputStream(IFileWriter* writer, std::ios_base::openmode mode = std::ios_base::trunc | std::ios_base::out);
~OutputStream();
private:
std::ostream* m_Stream;
};
~AbstractFileWriter();
AbstractFileWriter(const AbstractFileWriter& other);
AbstractFileWriter(const std::string& baseDataType);
AbstractFileWriter(const std::string& baseDataType, const CustomMimeType& mimeType, const std::string& description);
virtual us::ServiceProperties GetServiceProperties() const;
/**
* Registers a new CustomMimeType service object.
*
* This method is called from RegisterService and the default implementation
* registers a new mime-type service object if all of the following conditions
* are true:
*
* - TODO
*
* @param context
* @return
* @throws std::invalid_argument if \c context is NULL.
*/
virtual us::ServiceRegistration RegisterMimeType(us::ModuleContext* context);
void SetMimeType(const CustomMimeType& mimeType);
/**
* @return Get the mime-type this writer can handle.
*/
- CustomMimeType GetMimeType() const;
+ const CustomMimeType* GetMimeType() const;
void SetMimeTypePrefix(const std::string& prefix);
std::string GetMimeTypePrefix() const;
/**
* \brief Sets a human readable description of this writer.
*
* This will be used in file dialogs for example.
*/
void SetDescription(const std::string& description);
std::string GetDescription() const;
void SetDefaultOptions(const Options& defaultOptions);
Options GetDefaultOptions() const;
/**
* \brief Set the service ranking for this file writer.
*
* Default is zero and should only be chosen differently for a reason.
* The ranking is used to determine which writer to use if several
* equivalent writers have been found.
* It may be used to replace a default writer from MITK in your own project.
* E.g. if you want to use your own writer for nrrd files instead of the default,
* implement it and give it a higher ranking than zero.
*/
void SetRanking(int ranking);
int GetRanking() const;
/**
* \brief Sets the name of the mitk::Basedata that this writer is able to handle.
*
* The correct value is the one given as the first parameter in the mitkNewMacro of that BaseData derivate.
* You can also retrieve it by calling GetNameOfClass()
on an instance of said data.
*/
void SetBaseDataType(const std::string& baseDataType);
virtual std::string GetBaseDataType() const;
void ValidateOutputLocation() const;
private:
AbstractFileWriter& operator=(const AbstractFileWriter& other);
virtual mitk::IFileWriter* Clone() const = 0;
class Impl;
std::auto_ptr d;
};
} // namespace mitk
#endif /* AbstractFileWriter_H_HEADER_INCLUDED_C1E7E521 */
diff --git a/Core/Code/IO/mitkCustomMimeType.cpp b/Core/Code/IO/mitkCustomMimeType.cpp
index b25349b78c..240570efdb 100644
--- a/Core/Code/IO/mitkCustomMimeType.cpp
+++ b/Core/Code/IO/mitkCustomMimeType.cpp
@@ -1,144 +1,165 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
Copyright (c) German Cancer Research Center,
Division of Medical and Biological Informatics.
All rights reserved.
This software is distributed WITHOUT ANY WARRANTY; without
even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE.
See LICENSE.txt or http://www.mitk.org for details.
===================================================================*/
#include "mitkCustomMimeType.h"
#include "mitkMimeType.h"
#include
namespace mitk {
struct CustomMimeType::Impl
{
std::string m_Name;
std::string m_Category;
std::vector m_Extensions;
std::string m_Comment;
};
CustomMimeType::~CustomMimeType()
{
delete d;
}
CustomMimeType::CustomMimeType()
: d(new Impl)
{
}
CustomMimeType::CustomMimeType(const std::string& name)
: d(new Impl)
{
d->m_Name = name;
}
CustomMimeType::CustomMimeType(const CustomMimeType& other)
: d(new Impl(*other.d))
{
}
CustomMimeType::CustomMimeType(const MimeType& other)
: d(new Impl)
{
d->m_Name = other.GetName();
d->m_Category = other.GetCategory();
d->m_Extensions = other.GetExtensions();
d->m_Comment = other.GetComment();
}
CustomMimeType& CustomMimeType::operator=(const CustomMimeType& other)
{
CustomMimeType tmp(other);
Swap(tmp);
return *this;
}
CustomMimeType&CustomMimeType::operator=(const MimeType& other)
{
CustomMimeType tmp(other);
Swap(tmp);
return *this;
}
std::string CustomMimeType::GetName() const
{
return d->m_Name;
}
std::string CustomMimeType::GetCategory() const
{
return d->m_Category;
}
std::vector CustomMimeType::GetExtensions() const
{
return d->m_Extensions;
}
std::string CustomMimeType::GetComment() const
{
if (!d->m_Comment.empty()) return d->m_Comment;
if (!d->m_Extensions.empty())
{
return d->m_Extensions.front() + " File";
}
return "Unknown";
}
+bool CustomMimeType::AppliesTo(const std::string& path) const
+{
+ for (std::vector::const_iterator iter = d->m_Extensions.begin(),
+ iterEnd = d->m_Extensions.end(); iter != iterEnd; ++iter)
+ {
+ if (!iter->empty() && path.size() >= iter->size())
+ {
+ if (path.substr(path.size() - iter->size()) == *iter)
+ {
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
void CustomMimeType::SetName(const std::string& name)
{
d->m_Name = name;
}
void CustomMimeType::SetCategory(const std::string& category)
{
d->m_Category = category;
}
void CustomMimeType::SetExtension(const std::string& extension)
{
d->m_Extensions.clear();
d->m_Extensions.push_back(extension);
}
void CustomMimeType::AddExtension(const std::string& extension)
{
if (std::find(d->m_Extensions.begin(), d->m_Extensions.end(), extension) ==
d->m_Extensions.end())
{
d->m_Extensions.push_back(extension);
}
}
void CustomMimeType::SetComment(const std::string& comment)
{
d->m_Comment = comment;
}
void CustomMimeType::Swap(CustomMimeType& r)
{
Impl* d1 = d;
d = r.d;
r.d = d1;
}
+CustomMimeType* CustomMimeType::Clone() const
+{
+ return new CustomMimeType(*this);
+}
+
void swap(CustomMimeType& l, CustomMimeType& r)
{
l.Swap(r);
}
}
diff --git a/Core/Code/IO/mitkCustomMimeType.h b/Core/Code/IO/mitkCustomMimeType.h
index b232c58696..46a6a25a2f 100644
--- a/Core/Code/IO/mitkCustomMimeType.h
+++ b/Core/Code/IO/mitkCustomMimeType.h
@@ -1,70 +1,74 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
Copyright (c) German Cancer Research Center,
Division of Medical and Biological Informatics.
All rights reserved.
This software is distributed WITHOUT ANY WARRANTY; without
even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE.
See LICENSE.txt or http://www.mitk.org for details.
===================================================================*/
#ifndef MITKCUSTOMMIMETYPE_H
#define MITKCUSTOMMIMETYPE_H
#include
-#include
+#include
#include
#include
namespace mitk {
class MimeType;
class MITK_CORE_EXPORT CustomMimeType
{
public:
CustomMimeType();
CustomMimeType(const std::string& name);
CustomMimeType(const CustomMimeType& other);
explicit CustomMimeType(const MimeType& other);
- ~CustomMimeType();
+ virtual ~CustomMimeType();
CustomMimeType& operator=(const CustomMimeType& other);
CustomMimeType& operator=(const MimeType& other);
std::string GetName() const;
std::string GetCategory() const;
std::vector GetExtensions() const;
std::string GetComment() const;
+ virtual bool AppliesTo(const std::string& path) const;
+
void SetName(const std::string& name);
void SetCategory(const std::string& category);
void SetExtension(const std::string& extension);
void AddExtension(const std::string& extension);
void SetComment(const std::string& comment);
void Swap(CustomMimeType& r);
+ virtual CustomMimeType* Clone() const;
+
private:
struct Impl;
Impl* d;
};
void swap(CustomMimeType& l, CustomMimeType& r);
}
-US_DECLARE_SERVICE_INTERFACE(mitk::CustomMimeType, "org.mitk.CustomMimeType")
+MITK_DECLARE_SERVICE_INTERFACE(mitk::CustomMimeType, "org.mitk.CustomMimeType")
#endif // MITKCUSTOMMIMETYPE_H
diff --git a/Core/Code/IO/mitkDicomSeriesReader.cpp b/Core/Code/IO/mitkDicomSeriesReader.cpp
index fec7e5ef43..da388ffcd2 100644
--- a/Core/Code/IO/mitkDicomSeriesReader.cpp
+++ b/Core/Code/IO/mitkDicomSeriesReader.cpp
@@ -1,1781 +1,1777 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
Copyright (c) German Cancer Research Center,
Division of Medical and Biological Informatics.
All rights reserved.
This software is distributed WITHOUT ANY WARRANTY; without
even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE.
See LICENSE.txt or http://www.mitk.org for details.
===================================================================*/
// uncomment for learning more about the internal sorting mechanisms
//#define MBILOG_ENABLE_DEBUG
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "mitkProperties.h"
namespace mitk
{
-
std::string DicomSeriesReader::ReaderImplementationLevelToString( const ReaderImplementationLevel& enumValue )
{
switch (enumValue)
{
case ReaderImplementationLevel_Supported: return "Supported";
case ReaderImplementationLevel_PartlySupported: return "PartlySupported";
case ReaderImplementationLevel_Implemented: return "Implemented";
case ReaderImplementationLevel_Unsupported: return "Unsupported";
default: return "";
};
}
std::string DicomSeriesReader::PixelSpacingInterpretationToString( const PixelSpacingInterpretation& enumValue )
{
switch (enumValue)
{
case PixelSpacingInterpretation_SpacingInPatient: return "In Patient";
case PixelSpacingInterpretation_SpacingAtDetector: return "At Detector";
case PixelSpacingInterpretation_SpacingUnknown: return "Unknown spacing";
default: return "";
};
}
const DicomSeriesReader::TagToPropertyMapType& DicomSeriesReader::GetDICOMTagsToMITKPropertyMap()
{
static bool initialized = false;
static TagToPropertyMapType dictionary;
if (!initialized)
{
/*
Selection criteria:
- no sequences because we cannot represent that
- nothing animal related (specied, breed registration number), MITK focusses on human medical image processing.
- only general attributes so far
When extending this, we should make use of a real dictionary (GDCM/DCMTK and lookup the tag names there)
*/
// Patient module
dictionary["0010|0010"] = "dicom.patient.PatientsName";
dictionary["0010|0020"] = "dicom.patient.PatientID";
dictionary["0010|0030"] = "dicom.patient.PatientsBirthDate";
dictionary["0010|0040"] = "dicom.patient.PatientsSex";
dictionary["0010|0032"] = "dicom.patient.PatientsBirthTime";
dictionary["0010|1000"] = "dicom.patient.OtherPatientIDs";
dictionary["0010|1001"] = "dicom.patient.OtherPatientNames";
dictionary["0010|2160"] = "dicom.patient.EthnicGroup";
dictionary["0010|4000"] = "dicom.patient.PatientComments";
dictionary["0012|0062"] = "dicom.patient.PatientIdentityRemoved";
dictionary["0012|0063"] = "dicom.patient.DeIdentificationMethod";
// General Study module
dictionary["0020|000d"] = "dicom.study.StudyInstanceUID";
dictionary["0008|0020"] = "dicom.study.StudyDate";
dictionary["0008|0030"] = "dicom.study.StudyTime";
dictionary["0008|0090"] = "dicom.study.ReferringPhysiciansName";
dictionary["0020|0010"] = "dicom.study.StudyID";
dictionary["0008|0050"] = "dicom.study.AccessionNumber";
dictionary["0008|1030"] = "dicom.study.StudyDescription";
dictionary["0008|1048"] = "dicom.study.PhysiciansOfRecord";
dictionary["0008|1060"] = "dicom.study.NameOfPhysicianReadingStudy";
// General Series module
dictionary["0008|0060"] = "dicom.series.Modality";
dictionary["0020|000e"] = "dicom.series.SeriesInstanceUID";
dictionary["0020|0011"] = "dicom.series.SeriesNumber";
dictionary["0020|0060"] = "dicom.series.Laterality";
dictionary["0008|0021"] = "dicom.series.SeriesDate";
dictionary["0008|0031"] = "dicom.series.SeriesTime";
dictionary["0008|1050"] = "dicom.series.PerformingPhysiciansName";
dictionary["0018|1030"] = "dicom.series.ProtocolName";
dictionary["0008|103e"] = "dicom.series.SeriesDescription";
dictionary["0008|1070"] = "dicom.series.OperatorsName";
dictionary["0018|0015"] = "dicom.series.BodyPartExamined";
dictionary["0018|5100"] = "dicom.series.PatientPosition";
dictionary["0028|0108"] = "dicom.series.SmallestPixelValueInSeries";
dictionary["0028|0109"] = "dicom.series.LargestPixelValueInSeries";
// VOI LUT module
dictionary["0028|1050"] = "dicom.voilut.WindowCenter";
dictionary["0028|1051"] = "dicom.voilut.WindowWidth";
dictionary["0028|1055"] = "dicom.voilut.WindowCenterAndWidthExplanation";
// Image Pixel module
dictionary["0028|0004"] = "dicom.pixel.PhotometricInterpretation";
dictionary["0028|0010"] = "dicom.pixel.Rows";
dictionary["0028|0011"] = "dicom.pixel.Columns";
// Image Plane module
dictionary["0028|0030"] = "dicom.PixelSpacing";
dictionary["0018|1164"] = "dicom.ImagerPixelSpacing";
initialized = true;
}
return dictionary;
}
DataNode::Pointer
DicomSeriesReader::LoadDicomSeries(const StringContainer &filenames, bool sort, bool check_4d, bool correctTilt, UpdateCallBackMethod callback, Image::Pointer preLoadedImageBlock)
{
DataNode::Pointer node = DataNode::New();
if (DicomSeriesReader::LoadDicomSeries(filenames, *node, sort, check_4d, correctTilt, callback, preLoadedImageBlock))
{
if( filenames.empty() )
{
return NULL;
}
return node;
}
else
{
return NULL;
}
}
bool
DicomSeriesReader::LoadDicomSeries(const StringContainer &filenames,
DataNode &node,
bool sort,
bool check_4d,
bool correctTilt,
UpdateCallBackMethod callback,
itk::SmartPointer preLoadedImageBlock)
{
if( filenames.empty() )
{
MITK_DEBUG << "Calling LoadDicomSeries with empty filename string container. Probably invalid application logic.";
node.SetData(NULL);
return true; // this is not actually an error but the result is very simple
}
DcmIoType::Pointer io = DcmIoType::New();
try
{
if (io->CanReadFile(filenames.front().c_str()))
{
io->SetFileName(filenames.front().c_str());
io->ReadImageInformation();
if (io->GetPixelType() == itk::ImageIOBase::SCALAR ||
io->GetPixelType() == itk::ImageIOBase::RGB)
{
LoadDicom(filenames, node, sort, check_4d, correctTilt, callback, preLoadedImageBlock);
}
if (node.GetData())
{
return true;
}
}
}
catch(itk::MemoryAllocationError& e)
{
MITK_ERROR << "Out of memory. Cannot load DICOM series: " << e.what();
}
catch(std::exception& e)
{
MITK_ERROR << "Error encountered when loading DICOM series:" << e.what();
}
catch(...)
{
MITK_ERROR << "Unspecified error encountered when loading DICOM series.";
}
return false;
}
bool
DicomSeriesReader::IsDicom(const std::string &filename)
{
DcmIoType::Pointer io = DcmIoType::New();
return io->CanReadFile(filename.c_str());
}
bool
DicomSeriesReader::IsPhilips3DDicom(const std::string &filename)
{
DcmIoType::Pointer io = DcmIoType::New();
if (io->CanReadFile(filename.c_str()))
{
//Look at header Tag 3001,0010 if it is "Philips3D"
gdcm::Reader reader;
reader.SetFileName(filename.c_str());
reader.Read();
gdcm::DataSet &data_set = reader.GetFile().GetDataSet();
gdcm::StringFilter sf;
sf.SetFile(reader.GetFile());
if (data_set.FindDataElement(gdcm::Tag(0x3001, 0x0010)) &&
(sf.ToString(gdcm::Tag(0x3001, 0x0010)) == "Philips3D "))
{
return true;
}
}
return false;
}
bool
DicomSeriesReader::ReadPhilips3DDicom(const std::string &filename, itk::SmartPointer output_image)
{
// Now get PhilipsSpecific Tags
gdcm::PixmapReader reader;
reader.SetFileName(filename.c_str());
reader.Read();
gdcm::DataSet &data_set = reader.GetFile().GetDataSet();
gdcm::StringFilter sf;
sf.SetFile(reader.GetFile());
gdcm::Attribute<0x0028,0x0011> dimTagX; // coloumns || sagittal
gdcm::Attribute<0x3001,0x1001, gdcm::VR::UL, gdcm::VM::VM1> dimTagZ; //I have no idea what is VM1. // (Philips specific) // axial
gdcm::Attribute<0x0028,0x0010> dimTagY; // rows || coronal
gdcm::Attribute<0x0028,0x0008> dimTagT; // how many frames
gdcm::Attribute<0x0018,0x602c> spaceTagX; // Spacing in X , unit is "physicalTagx" (usually centimeter)
gdcm::Attribute<0x0018,0x602e> spaceTagY;
gdcm::Attribute<0x3001,0x1003, gdcm::VR::FD, gdcm::VM::VM1> spaceTagZ; // (Philips specific)
gdcm::Attribute<0x0018,0x6024> physicalTagX; // if 3, then spacing params are centimeter
gdcm::Attribute<0x0018,0x6026> physicalTagY;
gdcm::Attribute<0x3001,0x1002, gdcm::VR::US, gdcm::VM::VM1> physicalTagZ; // (Philips specific)
dimTagX.Set(data_set);
dimTagY.Set(data_set);
dimTagZ.Set(data_set);
dimTagT.Set(data_set);
spaceTagX.Set(data_set);
spaceTagY.Set(data_set);
spaceTagZ.Set(data_set);
physicalTagX.Set(data_set);
physicalTagY.Set(data_set);
physicalTagZ.Set(data_set);
unsigned int
dimX = dimTagX.GetValue(),
dimY = dimTagY.GetValue(),
dimZ = dimTagZ.GetValue(),
dimT = dimTagT.GetValue(),
physicalX = physicalTagX.GetValue(),
physicalY = physicalTagY.GetValue(),
physicalZ = physicalTagZ.GetValue();
float
spaceX = spaceTagX.GetValue(),
spaceY = spaceTagY.GetValue(),
spaceZ = spaceTagZ.GetValue();
if (physicalX == 3) // spacing parameter in cm, have to convert it to mm.
spaceX = spaceX * 10;
if (physicalY == 3) // spacing parameter in cm, have to convert it to mm.
spaceY = spaceY * 10;
if (physicalZ == 3) // spacing parameter in cm, have to convert it to mm.
spaceZ = spaceZ * 10;
// Ok, got all necessary Tags!
// Now read Pixeldata (7fe0,0010) X x Y x Z x T Elements
const gdcm::Pixmap &pixels = reader.GetPixmap();
gdcm::RAWCodec codec;
codec.SetPhotometricInterpretation(gdcm::PhotometricInterpretation::MONOCHROME2);
codec.SetPixelFormat(pixels.GetPixelFormat());
codec.SetPlanarConfiguration(0);
gdcm::DataElement out;
codec.Decode(data_set.GetDataElement(gdcm::Tag(0x7fe0, 0x0010)), out);
const gdcm::ByteValue *bv = out.GetByteValue();
const char *new_pixels = bv->GetPointer();
// Create MITK Image + Geometry
typedef itk::Image ImageType; //Pixeltype might be different sometimes? Maybe read it out from header
ImageType::RegionType myRegion;
ImageType::SizeType mySize;
ImageType::IndexType myIndex;
ImageType::SpacingType mySpacing;
ImageType::Pointer imageItk = ImageType::New();
mySpacing[0] = spaceX;
mySpacing[1] = spaceY;
mySpacing[2] = spaceZ;
mySpacing[3] = 1;
myIndex[0] = 0;
myIndex[1] = 0;
myIndex[2] = 0;
myIndex[3] = 0;
mySize[0] = dimX;
mySize[1] = dimY;
mySize[2] = dimZ;
mySize[3] = dimT;
myRegion.SetSize( mySize);
myRegion.SetIndex( myIndex );
imageItk->SetSpacing(mySpacing);
imageItk->SetRegions( myRegion);
imageItk->Allocate();
imageItk->FillBuffer(0);
itk::ImageRegionIterator iterator(imageItk, imageItk->GetLargestPossibleRegion());
iterator.GoToBegin();
unsigned long pixCount = 0;
unsigned long planeSize = dimX*dimY;
unsigned long planeCount = 0;
unsigned long timeCount = 0;
unsigned long numberOfSlices = dimZ;
while (!iterator.IsAtEnd())
{
unsigned long adressedPixel =
pixCount
+ (numberOfSlices-1-planeCount)*planeSize // add offset to adress the first pixel of current plane
+ timeCount*numberOfSlices*planeSize; // add time offset
iterator.Set( new_pixels[ adressedPixel ] );
pixCount++;
++iterator;
if (pixCount == planeSize)
{
pixCount = 0;
planeCount++;
}
if (planeCount == numberOfSlices)
{
planeCount = 0;
timeCount++;
}
if (timeCount == dimT)
{
break;
}
}
mitk::CastToMitkImage(imageItk, output_image);
return true; // actually never returns false yet.. but exception possible
}
std::string
DicomSeriesReader::ConstCharStarToString(const char* s)
{
return s ? std::string(s) : std::string();
}
bool
DicomSeriesReader::DICOMStringToSpacing(const std::string& s, ScalarType& spacingX, ScalarType& spacingY)
{
bool successful = false;
std::istringstream spacingReader(s);
std::string spacing;
if ( std::getline( spacingReader, spacing, '\\' ) )
{
spacingY = atof( spacing.c_str() );
if ( std::getline( spacingReader, spacing, '\\' ) )
{
spacingX = atof( spacing.c_str() );
successful = true;
}
}
return successful;
}
Point3D
DicomSeriesReader::DICOMStringToPoint3D(const std::string& s, bool& successful)
{
Point3D p;
successful = true;
std::istringstream originReader(s);
std::string coordinate;
unsigned int dim(0);
while( std::getline( originReader, coordinate, '\\' ) && dim < 3)
{
p[dim++]= atof(coordinate.c_str());
}
if (dim && dim != 3)
{
successful = false;
MITK_ERROR << "Reader implementation made wrong assumption on tag (0020,0032). Found " << dim << " instead of 3 values.";
}
else if (dim == 0)
{
successful = false;
p.Fill(0.0); // assume default (0,0,0)
}
return p;
}
void
DicomSeriesReader::DICOMStringToOrientationVectors(const std::string& s, Vector3D& right, Vector3D& up, bool& successful)
{
successful = true;
std::istringstream orientationReader(s);
std::string coordinate;
unsigned int dim(0);
while( std::getline( orientationReader, coordinate, '\\' ) && dim < 6 )
{
if (dim<3)
{
right[dim++] = atof(coordinate.c_str());
}
else
{
up[dim++ - 3] = atof(coordinate.c_str());
}
}
if (dim && dim != 6)
{
successful = false;
MITK_ERROR << "Reader implementation made wrong assumption on tag (0020,0037). Found " << dim << " instead of 6 values.";
}
else if (dim == 0)
{
// fill with defaults
right.Fill(0.0);
right[0] = 1.0;
up.Fill(0.0);
up[1] = 1.0;
successful = false;
}
}
DicomSeriesReader::SliceGroupingAnalysisResult
DicomSeriesReader::AnalyzeFileForITKImageSeriesReaderSpacingAssumption(
const StringContainer& files,
bool groupImagesWithGantryTilt,
const gdcm::Scanner::MappingType& tagValueMappings_)
{
// result.first = files that fit ITK's assumption
// result.second = files that do not fit, should be run through AnalyzeFileForITKImageSeriesReaderSpacingAssumption() again
SliceGroupingAnalysisResult result;
// we const_cast here, because I could not use a map.at(), which would make the code much more readable
gdcm::Scanner::MappingType& tagValueMappings = const_cast(tagValueMappings_);
const gdcm::Tag tagImagePositionPatient(0x0020,0x0032); // Image Position (Patient)
const gdcm::Tag tagImageOrientation(0x0020, 0x0037); // Image Orientation
const gdcm::Tag tagGantryTilt(0x0018, 0x1120); // gantry tilt
Vector3D fromFirstToSecondOrigin; fromFirstToSecondOrigin.Fill(0.0);
bool fromFirstToSecondOriginInitialized(false);
Point3D thisOrigin;
thisOrigin.Fill(0.0f);
Point3D lastOrigin;
lastOrigin.Fill(0.0f);
Point3D lastDifferentOrigin;
lastDifferentOrigin.Fill(0.0f);
bool lastOriginInitialized(false);
MITK_DEBUG << "--------------------------------------------------------------------------------";
MITK_DEBUG << "Analyzing files for z-spacing assumption of ITK's ImageSeriesReader (group tilted: " << groupImagesWithGantryTilt << ")";
unsigned int fileIndex(0);
for (StringContainer::const_iterator fileIter = files.begin();
fileIter != files.end();
++fileIter, ++fileIndex)
{
bool fileFitsIntoPattern(false);
std::string thisOriginString;
// Read tag value into point3D. PLEASE replace this by appropriate GDCM code if you figure out how to do that
thisOriginString = ConstCharStarToString( tagValueMappings[fileIter->c_str()][tagImagePositionPatient] );
if (thisOriginString.empty())
{
// don't let such files be in a common group. Everything without position information will be loaded as a single slice:
// with standard DICOM files this can happen to: CR, DX, SC
MITK_DEBUG << " ==> Sort away " << *fileIter << " for later analysis (no position information)"; // we already have one occupying this position
if ( result.GetBlockFilenames().empty() ) // nothing WITH position information yet
{
// ==> this is a group of its own, stop processing, come back later
result.AddFileToSortedBlock( *fileIter );
StringContainer remainingFiles;
remainingFiles.insert( remainingFiles.end(), fileIter+1, files.end() );
result.AddFilesToUnsortedBlock( remainingFiles );
fileFitsIntoPattern = false;
break; // no files anymore
}
else
{
// ==> this does not match, consider later
result.AddFileToUnsortedBlock( *fileIter );
fileFitsIntoPattern = false;
continue; // next file
}
}
bool ignoredConversionError(-42); // hard to get here, no graceful way to react
thisOrigin = DICOMStringToPoint3D( thisOriginString, ignoredConversionError );
MITK_DEBUG << " " << fileIndex << " " << *fileIter
<< " at "
/* << thisOriginString */ << "(" << thisOrigin[0] << "," << thisOrigin[1] << "," << thisOrigin[2] << ")";
if ( lastOriginInitialized && (thisOrigin == lastOrigin) )
{
MITK_DEBUG << " ==> Sort away " << *fileIter << " for separate time step"; // we already have one occupying this position
result.AddFileToUnsortedBlock( *fileIter );
fileFitsIntoPattern = false;
}
else
{
if (!fromFirstToSecondOriginInitialized && lastOriginInitialized) // calculate vector as soon as possible when we get a new position
{
fromFirstToSecondOrigin = thisOrigin - lastDifferentOrigin;
fromFirstToSecondOriginInitialized = true;
// Here we calculate if this slice and the previous one are well aligned,
// i.e. we test if the previous origin is on a line through the current
// origin, directed into the normal direction of the current slice.
// If this is NOT the case, then we have a data set with a TILTED GANTRY geometry,
// which cannot be simply loaded into a single mitk::Image at the moment.
// For this case, we flag this finding in the result and DicomSeriesReader
// can correct for that later.
Vector3D right; right.Fill(0.0);
Vector3D up; right.Fill(0.0); // might be down as well, but it is just a name at this point
DICOMStringToOrientationVectors( tagValueMappings[fileIter->c_str()][tagImageOrientation], right, up, ignoredConversionError );
GantryTiltInformation tiltInfo( lastDifferentOrigin, thisOrigin, right, up, 1 );
if ( tiltInfo.IsSheared() ) // mitk::eps is too small; 1/1000 of a mm should be enough to detect tilt
{
/* optimistic approach, accepting gantry tilt: save file for later, check all further files */
// at this point we have TWO slices analyzed! if they are the only two files, we still split, because there is no third to verify our tilting assumption.
// later with a third being available, we must check if the initial tilting vector is still valid. if yes, continue.
// if NO, we need to split the already sorted part (result.first) and the currently analyzed file (*fileIter)
// tell apart gantry tilt from overall skewedness
// sort out irregularly sheared slices, that IS NOT tilting
if ( groupImagesWithGantryTilt && tiltInfo.IsRegularGantryTilt() )
{
// check if this is at least roughly the same angle as recorded in DICOM tags
if ( tagValueMappings[fileIter->c_str()].find(tagGantryTilt) != tagValueMappings[fileIter->c_str()].end() )
{
// read value, compare to calculated angle
std::string tiltStr = ConstCharStarToString( tagValueMappings[fileIter->c_str()][tagGantryTilt] );
double angle = atof(tiltStr.c_str());
MITK_DEBUG << "Comparing recorded tilt angle " << angle << " against calculated value " << tiltInfo.GetTiltAngleInDegrees();
// TODO we probably want the signs correct, too (that depends: this is just a rough check, nothing serious)
// TODO TODO TODO when angle -27 and tiltangle 63, this will never trigger the if-clause... useless check in this case! old bug..?!
if ( fabs(angle) - tiltInfo.GetTiltAngleInDegrees() > 0.25)
{
result.AddFileToUnsortedBlock( *fileIter ); // sort away for further analysis
fileFitsIntoPattern = false;
}
else // tilt angle from header is less than 0.25 degrees different from what we calculated, assume this is fine
{
result.FlagGantryTilt();
result.AddFileToSortedBlock(*fileIter); // this file is good for current block
fileFitsIntoPattern = true;
}
}
else // we cannot check the calculated tilt angle against the one from the dicom header (so we assume we are right)
{
result.FlagGantryTilt();
result.AddFileToSortedBlock(*fileIter); // this file is good for current block
fileFitsIntoPattern = true;
}
}
else // caller does not want tilt compensation OR shearing is more complicated than tilt
{
result.AddFileToUnsortedBlock( *fileIter ); // sort away for further analysis
fileFitsIntoPattern = false;
}
}
else // not sheared
{
result.AddFileToSortedBlock(*fileIter); // this file is good for current block
fileFitsIntoPattern = true;
}
}
else if (fromFirstToSecondOriginInitialized) // we already know the offset between slices
{
Point3D assumedOrigin = lastDifferentOrigin + fromFirstToSecondOrigin;
Vector3D originError = assumedOrigin - thisOrigin;
double norm = originError.GetNorm();
double toleratedError(0.005); // max. 1/10mm error when measurement crosses 20 slices in z direction
if (norm > toleratedError)
{
MITK_DEBUG << " File does not fit into the inter-slice distance pattern (diff = "
<< norm << ", allowed "
<< toleratedError << ").";
MITK_DEBUG << " Expected position (" << assumedOrigin[0] << ","
<< assumedOrigin[1] << ","
<< assumedOrigin[2] << "), got position ("
<< thisOrigin[0] << ","
<< thisOrigin[1] << ","
<< thisOrigin[2] << ")";
MITK_DEBUG << " ==> Sort away " << *fileIter << " for later analysis";
// At this point we know we deviated from the expectation of ITK's ImageSeriesReader
// We split the input file list at this point, i.e. all files up to this one (excluding it)
// are returned as group 1, the remaining files (including the faulty one) are group 2
/* Optimistic approach: check if any of the remaining slices fits in */
result.AddFileToUnsortedBlock( *fileIter ); // sort away for further analysis
fileFitsIntoPattern = false;
}
else
{
result.AddFileToSortedBlock(*fileIter); // this file is good for current block
fileFitsIntoPattern = true;
}
}
else // this should be the very first slice
{
result.AddFileToSortedBlock(*fileIter); // this file is good for current block
fileFitsIntoPattern = true;
}
}
// record current origin for reference in later iterations
if ( !lastOriginInitialized || ( fileFitsIntoPattern && (thisOrigin != lastOrigin) ) )
{
lastDifferentOrigin = thisOrigin;
}
lastOrigin = thisOrigin;
lastOriginInitialized = true;
}
if ( result.ContainsGantryTilt() )
{
// check here how many files were grouped.
// IF it was only two files AND we assume tiltedness (e.g. save "distance")
// THEN we would want to also split the two previous files (simple) because
// we don't have any reason to assume they belong together
if ( result.GetBlockFilenames().size() == 2 )
{
result.UndoPrematureGrouping();
}
}
return result;
}
DicomSeriesReader::FileNamesGrouping
DicomSeriesReader::GetSeries(const StringContainer& files, bool groupImagesWithGantryTilt, const StringContainer &restrictions)
{
return GetSeries(files, true, groupImagesWithGantryTilt, restrictions);
}
DicomSeriesReader::FileNamesGrouping
DicomSeriesReader::GetSeries(const StringContainer& files, bool sortTo3DPlust, bool groupImagesWithGantryTilt, const StringContainer& /*restrictions*/)
{
/**
assumption about this method:
returns a map of uid-like-key --> list(filename)
each entry should contain filenames that have images of same
- series instance uid (automatically done by GDCMSeriesFileNames
- 0020,0037 image orientation (patient)
- 0028,0030 pixel spacing (x,y)
- 0018,0050 slice thickness
*/
// use GDCM directly, itk::GDCMSeriesFileNames does not work with GDCM 2
// PART I: scan files for sorting relevant DICOM tags,
// separate images that differ in any of those
// attributes (they cannot possibly form a 3D block)
// scan for relevant tags in dicom files
gdcm::Scanner scanner;
const gdcm::Tag tagSOPClassUID(0x0008, 0x0016); // SOP class UID
scanner.AddTag( tagSOPClassUID );
const gdcm::Tag tagSeriesInstanceUID(0x0020,0x000e); // Series Instance UID
scanner.AddTag( tagSeriesInstanceUID );
const gdcm::Tag tagImageOrientation(0x0020, 0x0037); // image orientation
scanner.AddTag( tagImageOrientation );
const gdcm::Tag tagPixelSpacing(0x0028, 0x0030); // pixel spacing
scanner.AddTag( tagPixelSpacing );
const gdcm::Tag tagImagerPixelSpacing(0x0018, 0x1164); // imager pixel spacing
scanner.AddTag( tagImagerPixelSpacing );
const gdcm::Tag tagSliceThickness(0x0018, 0x0050); // slice thickness
scanner.AddTag( tagSliceThickness );
const gdcm::Tag tagNumberOfRows(0x0028, 0x0010); // number rows
scanner.AddTag( tagNumberOfRows );
const gdcm::Tag tagNumberOfColumns(0x0028, 0x0011); // number cols
scanner.AddTag( tagNumberOfColumns );
const gdcm::Tag tagGantryTilt(0x0018, 0x1120); // gantry tilt
scanner.AddTag( tagGantryTilt );
const gdcm::Tag tagModality(0x0008, 0x0060); // modality
scanner.AddTag( tagModality );
const gdcm::Tag tagNumberOfFrames(0x0028, 0x0008); // number of frames
scanner.AddTag( tagNumberOfFrames );
// additional tags read in this scan to allow later analysis
// THESE tag are not used for initial separating of files
const gdcm::Tag tagImagePositionPatient(0x0020,0x0032); // Image Position (Patient)
scanner.AddTag( tagImagePositionPatient );
// TODO add further restrictions from arguments (when anybody asks for it)
FileNamesGrouping result;
// let GDCM scan files
if ( !scanner.Scan( files ) )
{
MITK_ERROR << "gdcm::Scanner failed when scanning " << files.size() << " input files.";
return result;
}
// assign files IDs that will separate them for loading into image blocks
for (gdcm::Scanner::ConstIterator fileIter = scanner.Begin();
fileIter != scanner.End();
++fileIter)
{
if ( std::string(fileIter->first).empty() ) continue; // TODO understand why Scanner has empty string entries
if ( std::string(fileIter->first) == std::string("DICOMDIR") ) continue;
/* sort out multi-frame
if ( scanner.GetValue( fileIter->first , tagNumberOfFrames ) )
{
MITK_INFO << "Ignoring " << fileIter->first << " because we cannot handle multi-frame images.";
continue;
}
*/
// we const_cast here, because I could not use a map.at() function in CreateMoreUniqueSeriesIdentifier.
// doing the same thing with find would make the code less readable. Since we forget the Scanner results
// anyway after this function, we can simply tolerate empty map entries introduced by bad operator[] access
std::string moreUniqueSeriesId = CreateMoreUniqueSeriesIdentifier( const_cast(fileIter->second) );
result[ moreUniqueSeriesId ].AddFile( fileIter->first );
}
// PART II: sort slices spatially (or at least consistently if this is NOT possible, see method)
for ( FileNamesGrouping::const_iterator groupIter = result.begin();
groupIter != result.end();
++groupIter )
{
try
{
result[ groupIter->first ] = ImageBlockDescriptor( SortSeriesSlices( groupIter->second.GetFilenames() ) ); // sort each slice group spatially
} catch(...)
{
MITK_ERROR << "Caught something.";
}
}
// PART III: analyze pre-sorted images for valid blocks (i.e. blocks of equal z-spacing),
// separate into multiple blocks if necessary.
//
// Analysis performs the following steps:
// * imitate itk::ImageSeriesReader: use the distance between the first two images as z-spacing
// * check what images actually fulfill ITK's z-spacing assumption
// * separate all images that fail the test into new blocks, re-iterate analysis for these blocks
// * this includes images which DO NOT PROVIDE spatial information, i.e. all images w/o ImagePositionPatient will be loaded separately
FileNamesGrouping groupsOf3DPlusTBlocks; // final result of this function
for ( FileNamesGrouping::const_iterator groupIter = result.begin();
groupIter != result.end();
++groupIter )
{
FileNamesGrouping groupsOf3DBlocks; // intermediate result for only this group(!)
std::map mapOf3DBlockAnalysisResults;
StringContainer filesStillToAnalyze = groupIter->second.GetFilenames();
std::string groupUID = groupIter->first;
unsigned int subgroup(0);
MITK_DEBUG << "Analyze group " << groupUID << " of " << groupIter->second.GetFilenames().size() << " files";
while (!filesStillToAnalyze.empty()) // repeat until all files are grouped somehow
{
SliceGroupingAnalysisResult analysisResult =
AnalyzeFileForITKImageSeriesReaderSpacingAssumption( filesStillToAnalyze,
groupImagesWithGantryTilt,
scanner.GetMappings() );
// enhance the UID for additional groups
std::stringstream newGroupUID;
newGroupUID << groupUID << '.' << subgroup;
ImageBlockDescriptor thisBlock( analysisResult.GetBlockFilenames() );
std::string firstFileInBlock = thisBlock.GetFilenames().front();
thisBlock.SetImageBlockUID( newGroupUID.str() );
thisBlock.SetSeriesInstanceUID( DicomSeriesReader::ConstCharStarToString( scanner.GetValue( firstFileInBlock.c_str(), tagSeriesInstanceUID ) ) );
thisBlock.SetHasGantryTiltCorrected( analysisResult.ContainsGantryTilt() );
thisBlock.SetSOPClassUID( DicomSeriesReader::ConstCharStarToString( scanner.GetValue( firstFileInBlock.c_str(), tagSOPClassUID ) ) );
thisBlock.SetNumberOfFrames( ConstCharStarToString( scanner.GetValue( firstFileInBlock.c_str(), tagNumberOfFrames ) ) );
thisBlock.SetModality( DicomSeriesReader::ConstCharStarToString( scanner.GetValue( firstFileInBlock.c_str(), tagModality ) ) );
thisBlock.SetPixelSpacingInformation( DicomSeriesReader::ConstCharStarToString( scanner.GetValue( firstFileInBlock.c_str(), tagPixelSpacing ) ),
DicomSeriesReader::ConstCharStarToString( scanner.GetValue( firstFileInBlock.c_str(), tagImagerPixelSpacing ) ) );
thisBlock.SetHasMultipleTimePoints( false );
groupsOf3DBlocks[ newGroupUID.str() ] = thisBlock;
//MITK_DEBUG << "Result: sorted 3D group " << newGroupUID.str() << " with " << groupsOf3DBlocks[ newGroupUID.str() ].GetFilenames().size() << " files";
MITK_DEBUG << "Result: sorted 3D group with " << groupsOf3DBlocks[ newGroupUID.str() ].GetFilenames().size() << " files";
StringContainer debugOutputFiles = analysisResult.GetBlockFilenames();
for (StringContainer::const_iterator siter = debugOutputFiles.begin(); siter != debugOutputFiles.end(); ++siter)
MITK_DEBUG << " IN " << *siter;
++subgroup;
filesStillToAnalyze = analysisResult.GetUnsortedFilenames(); // remember what needs further analysis
for (StringContainer::const_iterator siter = filesStillToAnalyze.begin(); siter != filesStillToAnalyze.end(); ++siter)
MITK_DEBUG << " OUT " << *siter;
-
}
// end of grouping, now post-process groups
// PART IV: attempt to group blocks to 3D+t blocks if requested
// inspect entries of groupsOf3DBlocks
// - if number of files is identical to previous entry, collect for 3D+t block
// - as soon as number of files changes from previous entry, record collected blocks as 3D+t block, start a new one, continue
// decide whether or not to group 3D blocks into 3D+t blocks where possible
if ( !sortTo3DPlust )
{
// copy 3D blocks to output
groupsOf3DPlusTBlocks.insert( groupsOf3DBlocks.begin(), groupsOf3DBlocks.end() );
}
else
{
// sort 3D+t (as described in "PART IV")
MITK_DEBUG << "================================================================================";
MITK_DEBUG << "3D+t analysis:";
unsigned int numberOfFilesInPreviousBlock(0);
std::string previousBlockKey;
for ( FileNamesGrouping::const_iterator block3DIter = groupsOf3DBlocks.begin();
block3DIter != groupsOf3DBlocks.end();
++block3DIter )
{
unsigned int numberOfFilesInThisBlock = block3DIter->second.GetFilenames().size();
std::string thisBlockKey = block3DIter->first;
if (numberOfFilesInPreviousBlock == 0)
{
numberOfFilesInPreviousBlock = numberOfFilesInThisBlock;
groupsOf3DPlusTBlocks[thisBlockKey] = block3DIter->second;
MITK_DEBUG << " 3D+t group " << thisBlockKey;
previousBlockKey = thisBlockKey;
}
else
{
bool identicalOrigins;
try {
// check whether this and the previous block share a comon origin
// TODO should be safe, but a little try/catch or other error handling wouldn't hurt
const char
*origin_value = scanner.GetValue( groupsOf3DBlocks[thisBlockKey].GetFilenames().front().c_str(), tagImagePositionPatient ),
*previous_origin_value = scanner.GetValue( groupsOf3DBlocks[previousBlockKey].GetFilenames().front().c_str(), tagImagePositionPatient ),
*destination_value = scanner.GetValue( groupsOf3DBlocks[thisBlockKey].GetFilenames().back().c_str(), tagImagePositionPatient ),
*previous_destination_value = scanner.GetValue( groupsOf3DBlocks[previousBlockKey].GetFilenames().back().c_str(), tagImagePositionPatient );
if (!origin_value || !previous_origin_value || !destination_value || !previous_destination_value)
{
identicalOrigins = false;
}
else
{
std::string thisOriginString = ConstCharStarToString( origin_value );
std::string previousOriginString = ConstCharStarToString( previous_origin_value );
// also compare last origin, because this might differ if z-spacing is different
std::string thisDestinationString = ConstCharStarToString( destination_value );
std::string previousDestinationString = ConstCharStarToString( previous_destination_value );
identicalOrigins = ( (thisOriginString == previousOriginString) && (thisDestinationString == previousDestinationString) );
}
-
} catch(...)
{
identicalOrigins = false;
}
if (identicalOrigins && (numberOfFilesInPreviousBlock == numberOfFilesInThisBlock))
{
// group with previous block
groupsOf3DPlusTBlocks[previousBlockKey].AddFiles( block3DIter->second.GetFilenames() );
groupsOf3DPlusTBlocks[previousBlockKey].SetHasMultipleTimePoints(true);
MITK_DEBUG << " --> group enhanced with another timestep";
}
else
{
// start a new block
groupsOf3DPlusTBlocks[thisBlockKey] = block3DIter->second;
int numberOfTimeSteps = groupsOf3DPlusTBlocks[previousBlockKey].GetFilenames().size() / numberOfFilesInPreviousBlock;
MITK_DEBUG << " ==> group closed with " << numberOfTimeSteps << " time steps";
previousBlockKey = thisBlockKey;
MITK_DEBUG << " 3D+t group " << thisBlockKey << " started";
}
}
numberOfFilesInPreviousBlock = numberOfFilesInThisBlock;
}
}
}
MITK_DEBUG << "================================================================================";
MITK_DEBUG << "Summary: ";
for ( FileNamesGrouping::const_iterator groupIter = groupsOf3DPlusTBlocks.begin(); groupIter != groupsOf3DPlusTBlocks.end(); ++groupIter )
{
ImageBlockDescriptor block = groupIter->second;
MITK_DEBUG << " " << block.GetFilenames().size() << " '" << block.GetModality() << "' images (" << block.GetSOPClassUIDAsString() << ") in volume " << block.GetImageBlockUID();
MITK_DEBUG << " (gantry tilt : " << (block.HasGantryTiltCorrected()?"Yes":"No") << "; "
"pixel spacing : " << PixelSpacingInterpretationToString( block.GetPixelSpacingType() ) << "; "
"3D+t: " << (block.HasMultipleTimePoints()?"Yes":"No") << "; "
"reader support: " << ReaderImplementationLevelToString( block.GetReaderImplementationLevel() ) << ")";
StringContainer debugOutputFiles = block.GetFilenames();
for (StringContainer::const_iterator siter = debugOutputFiles.begin(); siter != debugOutputFiles.end(); ++siter)
MITK_DEBUG << " F " << *siter;
}
MITK_DEBUG << "================================================================================";
return groupsOf3DPlusTBlocks;
}
DicomSeriesReader::FileNamesGrouping
DicomSeriesReader::GetSeries(const std::string &dir, bool groupImagesWithGantryTilt, const StringContainer &restrictions)
{
gdcm::Directory directoryLister;
directoryLister.Load( dir.c_str(), false ); // non-recursive
return GetSeries(directoryLister.GetFilenames(), groupImagesWithGantryTilt, restrictions);
}
std::string
DicomSeriesReader::CreateSeriesIdentifierPart( gdcm::Scanner::TagToValue& tagValueMap, const gdcm::Tag& tag )
{
std::string result;
try
{
result = IDifyTagValue( tagValueMap[ tag ] ? tagValueMap[ tag ] : std::string("") );
}
catch (std::exception&)
{
// we are happy with even nothing, this will just group images of a series
//MITK_WARN << "Could not access tag " << tag << ": " << e.what();
}
return result;
}
std::string
DicomSeriesReader::CreateMoreUniqueSeriesIdentifier( gdcm::Scanner::TagToValue& tagValueMap )
{
const gdcm::Tag tagSeriesInstanceUID(0x0020,0x000e); // Series Instance UID
const gdcm::Tag tagImageOrientation(0x0020, 0x0037); // image orientation
const gdcm::Tag tagPixelSpacing(0x0028, 0x0030); // pixel spacing
const gdcm::Tag tagImagerPixelSpacing(0x0018, 0x1164); // imager pixel spacing
const gdcm::Tag tagSliceThickness(0x0018, 0x0050); // slice thickness
const gdcm::Tag tagNumberOfRows(0x0028, 0x0010); // number rows
const gdcm::Tag tagNumberOfColumns(0x0028, 0x0011); // number cols
const gdcm::Tag tagNumberOfFrames(0x0028, 0x0008); // number of frames
const char* tagSeriesInstanceUid = tagValueMap[tagSeriesInstanceUID];
if (!tagSeriesInstanceUid)
{
mitkThrow() << "CreateMoreUniqueSeriesIdentifier() could not access series instance UID. Something is seriously wrong with this image, so stopping here.";
}
std::string constructedID = tagSeriesInstanceUid;
constructedID += CreateSeriesIdentifierPart( tagValueMap, tagNumberOfRows );
constructedID += CreateSeriesIdentifierPart( tagValueMap, tagNumberOfColumns );
constructedID += CreateSeriesIdentifierPart( tagValueMap, tagPixelSpacing );
constructedID += CreateSeriesIdentifierPart( tagValueMap, tagImagerPixelSpacing );
constructedID += CreateSeriesIdentifierPart( tagValueMap, tagSliceThickness );
constructedID += CreateSeriesIdentifierPart( tagValueMap, tagNumberOfFrames );
// be a bit tolerant for orienatation, let only the first few digits matter (http://bugs.mitk.org/show_bug.cgi?id=12263)
// NOT constructedID += CreateSeriesIdentifierPart( tagValueMap, tagImageOrientation );
if (tagValueMap.find(tagImageOrientation) != tagValueMap.end())
{
bool conversionError(false);
Vector3D right; right.Fill(0.0);
Vector3D up; right.Fill(0.0);
DICOMStringToOrientationVectors( tagValueMap[tagImageOrientation], right, up, conversionError );
//string newstring sprintf(simplifiedOrientationString, "%.3f\\%.3f\\%.3f\\%.3f\\%.3f\\%.3f", right[0], right[1], right[2], up[0], up[1], up[2]);
std::ostringstream ss;
ss.setf(std::ios::fixed, std::ios::floatfield);
ss.precision(5);
ss << right[0] << "\\"
<< right[1] << "\\"
<< right[2] << "\\"
<< up[0] << "\\"
<< up[1] << "\\"
<< up[2];
std::string simplifiedOrientationString(ss.str());
constructedID += IDifyTagValue( simplifiedOrientationString );
}
constructedID.resize( constructedID.length() - 1 ); // cut of trailing '.'
return constructedID;
}
std::string
DicomSeriesReader::IDifyTagValue(const std::string& value)
{
std::string IDifiedValue( value );
if (value.empty()) throw std::logic_error("IDifyTagValue() illegaly called with empty tag value");
// Eliminate non-alnum characters, including whitespace...
// that may have been introduced by concats.
for(std::size_t i=0; i= 'a' && IDifiedValue[i] <= 'z')
|| (IDifiedValue[i] >= '0' && IDifiedValue[i] <= '9')
|| (IDifiedValue[i] >= 'A' && IDifiedValue[i] <= 'Z')))
{
IDifiedValue.erase(i, 1);
}
}
IDifiedValue += ".";
return IDifiedValue;
}
DicomSeriesReader::StringContainer
DicomSeriesReader::GetSeries(const std::string &dir, const std::string &series_uid, bool groupImagesWithGantryTilt, const StringContainer &restrictions)
{
FileNamesGrouping allSeries = GetSeries(dir, groupImagesWithGantryTilt, restrictions);
StringContainer resultingFileList;
for ( FileNamesGrouping::const_iterator idIter = allSeries.begin();
idIter != allSeries.end();
++idIter )
{
if ( idIter->first.find( series_uid ) == 0 ) // this ID starts with given series_uid
{
return idIter->second.GetFilenames();
}
}
return resultingFileList;
}
DicomSeriesReader::StringContainer
DicomSeriesReader::SortSeriesSlices(const StringContainer &unsortedFilenames)
{
/* we CAN expect a group of equal
- series instance uid
- image orientation
- pixel spacing
- imager pixel spacing
- slice thickness
- number of rows/columns
(each piece of information except the rows/columns might be missing)
sorting with GdcmSortFunction tries its best by sorting by spatial position
and more hints (acquisition number, acquisition time, trigger time) but will
always produce a sorting by falling back to SOP Instance UID.
*/
gdcm::Sorter sorter;
sorter.SetSortFunction(DicomSeriesReader::GdcmSortFunction);
try
{
if (sorter.Sort(unsortedFilenames))
{
return sorter.GetFilenames();
}
else
{
MITK_WARN << "Sorting error. Leaving series unsorted.";
return unsortedFilenames;
}
}
catch(std::logic_error&)
{
MITK_WARN << "Sorting error. Leaving series unsorted.";
return unsortedFilenames;
}
}
bool
DicomSeriesReader::GdcmSortFunction(const gdcm::DataSet &ds1, const gdcm::DataSet &ds2)
{
// This method MUST accept missing location and position information (and all else, too)
// because we cannot rely on anything
// (restriction on the sentence before: we have to provide consistent sorting, so we
// rely on the minimum information all DICOM files need to provide: SOP Instance UID)
/* we CAN expect a group of equal
- series instance uid
- image orientation
- pixel spacing
- imager pixel spacing
- slice thickness
- number of rows/columns
*/
static const gdcm::Tag tagImagePositionPatient(0x0020,0x0032); // Image Position (Patient)
static const gdcm::Tag tagImageOrientation(0x0020, 0x0037); // Image Orientation
// see if we have Image Position and Orientation
if ( ds1.FindDataElement(tagImagePositionPatient) && ds1.FindDataElement(tagImageOrientation) &&
ds2.FindDataElement(tagImagePositionPatient) && ds2.FindDataElement(tagImageOrientation) )
{
gdcm::Attribute<0x0020,0x0032> image_pos1; // Image Position (Patient)
gdcm::Attribute<0x0020,0x0037> image_orientation1; // Image Orientation (Patient)
image_pos1.Set(ds1);
image_orientation1.Set(ds1);
gdcm::Attribute<0x0020,0x0032> image_pos2;
gdcm::Attribute<0x0020,0x0037> image_orientation2;
image_pos2.Set(ds2);
image_orientation2.Set(ds2);
/*
we tolerate very small differences in image orientation, since we got to know about
acquisitions where these values change across a single series (7th decimal digit)
(http://bugs.mitk.org/show_bug.cgi?id=12263)
still, we want to check if our assumption of 'almost equal' orientations is valid
*/
for (unsigned int dim = 0; dim < 6; ++dim)
{
if ( fabs(image_orientation2[dim] - image_orientation1[dim]) > 0.0001 )
{
MITK_ERROR << "Dicom images have different orientations.";
throw std::logic_error("Dicom images have different orientations. Call GetSeries() first to separate images.");
}
}
double normal[3];
normal[0] = image_orientation1[1] * image_orientation1[5] - image_orientation1[2] * image_orientation1[4];
normal[1] = image_orientation1[2] * image_orientation1[3] - image_orientation1[0] * image_orientation1[5];
normal[2] = image_orientation1[0] * image_orientation1[4] - image_orientation1[1] * image_orientation1[3];
double
dist1 = 0.0,
dist2 = 0.0;
// this computes the distance from world origin (0,0,0) ALONG THE NORMAL of the image planes
for (unsigned char i = 0u; i < 3u; ++i)
{
dist1 += normal[i] * image_pos1[i];
dist2 += normal[i] * image_pos2[i];
}
// if we can sort by just comparing the distance, we do exactly that
if ( fabs(dist1 - dist2) >= mitk::eps)
{
// default: compare position
return dist1 < dist2;
}
else // we need to check more properties to distinguish slices
{
// try to sort by Acquisition Number
static const gdcm::Tag tagAcquisitionNumber(0x0020, 0x0012);
if (ds1.FindDataElement(tagAcquisitionNumber) && ds2.FindDataElement(tagAcquisitionNumber))
{
gdcm::Attribute<0x0020,0x0012> acquisition_number1; // Acquisition number
gdcm::Attribute<0x0020,0x0012> acquisition_number2;
acquisition_number1.Set(ds1);
acquisition_number2.Set(ds2);
if (acquisition_number1 != acquisition_number2)
{
return acquisition_number1 < acquisition_number2;
}
else // neither position nor acquisition number are good for sorting, so check more
{
// try to sort by Acquisition Time
static const gdcm::Tag tagAcquisitionTime(0x0008, 0x0032);
if (ds1.FindDataElement(tagAcquisitionTime) && ds2.FindDataElement(tagAcquisitionTime))
{
gdcm::Attribute<0x0008,0x0032> acquisition_time1; // Acquisition time
gdcm::Attribute<0x0008,0x0032> acquisition_time2;
acquisition_time1.Set(ds1);
acquisition_time2.Set(ds2);
if (acquisition_time1 != acquisition_time2)
{
return acquisition_time1 < acquisition_time2;
}
else // we gave up on image position, acquisition number and acquisition time now
{
// let's try trigger time
static const gdcm::Tag tagTriggerTime(0x0018, 0x1060);
if (ds1.FindDataElement(tagTriggerTime) && ds2.FindDataElement(tagTriggerTime))
{
gdcm::Attribute<0x0018,0x1060> trigger_time1; // Trigger time
gdcm::Attribute<0x0018,0x1060> trigger_time2;
trigger_time1.Set(ds1);
trigger_time2.Set(ds2);
if (trigger_time1 != trigger_time2)
{
return trigger_time1 < trigger_time2;
}
// ELSE!
// for this and many previous ifs we fall through if nothing lets us sort
} // .
} // .
} // .
}
}
}
} // .
// LAST RESORT: all valuable information for sorting is missing.
// Sort by some meaningless but unique identifiers to satisfy the sort function
static const gdcm::Tag tagSOPInstanceUID(0x0008, 0x0018);
if (ds1.FindDataElement(tagSOPInstanceUID) && ds2.FindDataElement(tagSOPInstanceUID))
{
MITK_DEBUG << "Dicom images are missing attributes for a meaningful sorting, falling back to SOP instance UID comparison.";
gdcm::Attribute<0x0008,0x0018> SOPInstanceUID1; // SOP instance UID is mandatory and unique
gdcm::Attribute<0x0008,0x0018> SOPInstanceUID2;
SOPInstanceUID1.Set(ds1);
SOPInstanceUID2.Set(ds2);
return SOPInstanceUID1 < SOPInstanceUID2;
}
else
{
// no DICOM file should really come down here, this should only be reached with unskillful and unlucky manipulation of files
std::string error_message("Malformed DICOM images, which do not even contain a SOP Instance UID.");
MITK_ERROR << error_message;
throw std::logic_error( error_message );
}
}
std::string DicomSeriesReader::GetConfigurationString()
{
std::stringstream configuration;
configuration << "MITK_USE_GDCMIO: ";
configuration << "true";
configuration << "\n";
configuration << "GDCM_VERSION: ";
#ifdef GDCM_MAJOR_VERSION
configuration << GDCM_VERSION;
#endif
//configuration << "\n";
return configuration.str();
}
void DicomSeriesReader::CopyMetaDataToImageProperties(StringContainer filenames, const gdcm::Scanner::MappingType &tagValueMappings_, DcmIoType *io, const ImageBlockDescriptor& blockInfo, Image *image)
{
std::list imageBlock;
imageBlock.push_back(filenames);
CopyMetaDataToImageProperties(imageBlock, tagValueMappings_, io, blockInfo, image);
}
void DicomSeriesReader::CopyMetaDataToImageProperties( std::list imageBlock, const gdcm::Scanner::MappingType& tagValueMappings_, DcmIoType* io, const ImageBlockDescriptor& blockInfo, Image* image)
{
if (!io || !image) return;
StringLookupTable filesForSlices;
StringLookupTable sliceLocationForSlices;
StringLookupTable instanceNumberForSlices;
StringLookupTable SOPInstanceNumberForSlices;
gdcm::Scanner::MappingType& tagValueMappings = const_cast(tagValueMappings_);
//DICOM tags which should be added to the image properties
const gdcm::Tag tagSliceLocation(0x0020, 0x1041); // slice location
const gdcm::Tag tagInstanceNumber(0x0020, 0x0013); // (image) instance number
const gdcm::Tag tagSOPInstanceNumber(0x0008, 0x0018); // SOP instance number
unsigned int timeStep(0);
std::string propertyKeySliceLocation = "dicom.image.0020.1041";
std::string propertyKeyInstanceNumber = "dicom.image.0020.0013";
std::string propertyKeySOPInstanceNumber = "dicom.image.0008.0018";
// tags for each image
for ( std::list::iterator i = imageBlock.begin(); i != imageBlock.end(); i++, timeStep++ )
{
-
const StringContainer& files = (*i);
unsigned int slice(0);
for ( StringContainer::const_iterator fIter = files.begin();
fIter != files.end();
++fIter, ++slice )
{
filesForSlices.SetTableValue( slice, *fIter );
gdcm::Scanner::TagToValue tagValueMapForFile = tagValueMappings[fIter->c_str()];
if(tagValueMapForFile.find(tagSliceLocation) != tagValueMapForFile.end())
sliceLocationForSlices.SetTableValue(slice, tagValueMapForFile[tagSliceLocation]);
if(tagValueMapForFile.find(tagInstanceNumber) != tagValueMapForFile.end())
instanceNumberForSlices.SetTableValue(slice, tagValueMapForFile[tagInstanceNumber]);
if(tagValueMapForFile.find(tagSOPInstanceNumber) != tagValueMapForFile.end())
SOPInstanceNumberForSlices.SetTableValue(slice, tagValueMapForFile[tagSOPInstanceNumber]);
}
image->SetProperty( "files", StringLookupTableProperty::New( filesForSlices ) );
//If more than one time step add postfix ".t" + timestep
if(timeStep != 0)
{
std::ostringstream postfix;
postfix << ".t" << timeStep;
propertyKeySliceLocation.append(postfix.str());
propertyKeyInstanceNumber.append(postfix.str());
propertyKeySOPInstanceNumber.append(postfix.str());
}
image->SetProperty( propertyKeySliceLocation.c_str(), StringLookupTableProperty::New( sliceLocationForSlices ) );
image->SetProperty( propertyKeyInstanceNumber.c_str(), StringLookupTableProperty::New( instanceNumberForSlices ) );
image->SetProperty( propertyKeySOPInstanceNumber.c_str(), StringLookupTableProperty::New( SOPInstanceNumberForSlices ) );
}
// Copy tags for series, study, patient level (leave interpretation to application).
// These properties will be copied to the DataNode by DicomSeriesReader.
// tags for the series (we just use the one that ITK copied to its dictionary (proably that of the last slice)
const itk::MetaDataDictionary& dict = io->GetMetaDataDictionary();
const TagToPropertyMapType& propertyLookup = DicomSeriesReader::GetDICOMTagsToMITKPropertyMap();
itk::MetaDataDictionary::ConstIterator dictIter = dict.Begin();
while ( dictIter != dict.End() )
{
//MITK_DEBUG << "Key " << dictIter->first;
std::string value;
if ( itk::ExposeMetaData( dict, dictIter->first, value ) )
{
//MITK_DEBUG << "Value " << value;
TagToPropertyMapType::const_iterator valuePosition = propertyLookup.find( dictIter->first );
if ( valuePosition != propertyLookup.end() )
{
std::string propertyKey = valuePosition->second;
//MITK_DEBUG << "--> " << propertyKey;
image->SetProperty( propertyKey.c_str(), StringProperty::New(value) );
}
}
else
{
MITK_WARN << "Tag " << dictIter->first << " not read as string as expected. Ignoring..." ;
}
++dictIter;
}
// copy imageblockdescriptor as properties
image->SetProperty("dicomseriesreader.SOPClass", StringProperty::New(blockInfo.GetSOPClassUIDAsString()));
image->SetProperty("dicomseriesreader.ReaderImplementationLevelString", StringProperty::New(ReaderImplementationLevelToString( blockInfo.GetReaderImplementationLevel() )));
image->SetProperty("dicomseriesreader.ReaderImplementationLevel", GenericProperty::New( blockInfo.GetReaderImplementationLevel() ));
image->SetProperty("dicomseriesreader.PixelSpacingInterpretationString", StringProperty::New(PixelSpacingInterpretationToString( blockInfo.GetPixelSpacingType() )));
image->SetProperty("dicomseriesreader.PixelSpacingInterpretation", GenericProperty::New(blockInfo.GetPixelSpacingType()));
image->SetProperty("dicomseriesreader.MultiFrameImage", BoolProperty::New(blockInfo.IsMultiFrameImage()));
image->SetProperty("dicomseriesreader.GantyTiltCorrected", BoolProperty::New(blockInfo.HasGantryTiltCorrected()));
image->SetProperty("dicomseriesreader.3D+t", BoolProperty::New(blockInfo.HasMultipleTimePoints()));
}
void DicomSeriesReader::FixSpacingInformation( mitk::Image* image, const ImageBlockDescriptor& imageBlockDescriptor )
{
// spacing provided by ITK/GDCM
Vector3D imageSpacing = image->GetGeometry()->GetSpacing();
ScalarType imageSpacingX = imageSpacing[0];
ScalarType imageSpacingY = imageSpacing[1];
// spacing as desired by MITK (preference for "in patient", else "on detector", or "1.0/1.0")
ScalarType desiredSpacingX = imageSpacingX;
ScalarType desiredSpacingY = imageSpacingY;
imageBlockDescriptor.GetDesiredMITKImagePixelSpacing( desiredSpacingX, desiredSpacingY );
MITK_DEBUG << "Loaded spacing: " << imageSpacingX << "/" << imageSpacingY;
MITK_DEBUG << "Corrected spacing: " << desiredSpacingX << "/" << desiredSpacingY;
imageSpacing[0] = desiredSpacingX;
imageSpacing[1] = desiredSpacingY;
image->GetGeometry()->SetSpacing( imageSpacing );
}
void DicomSeriesReader::LoadDicom(const StringContainer &filenames, DataNode &node, bool sort, bool load4D, bool correctTilt, UpdateCallBackMethod callback, Image::Pointer preLoadedImageBlock)
{
const char* previousCLocale = setlocale(LC_NUMERIC, NULL);
setlocale(LC_NUMERIC, "C");
std::locale previousCppLocale( std::cin.getloc() );
std::locale l( "C" );
std::cin.imbue(l);
ImageBlockDescriptor imageBlockDescriptor;
const gdcm::Tag tagImagePositionPatient(0x0020,0x0032); // Image Position (Patient)
const gdcm::Tag tagImageOrientation(0x0020, 0x0037); // Image Orientation
const gdcm::Tag tagSeriesInstanceUID(0x0020, 0x000e); // Series Instance UID
const gdcm::Tag tagSOPClassUID(0x0008, 0x0016); // SOP class UID
const gdcm::Tag tagModality(0x0008, 0x0060); // modality
const gdcm::Tag tagPixelSpacing(0x0028, 0x0030); // pixel spacing
const gdcm::Tag tagImagerPixelSpacing(0x0018, 0x1164); // imager pixel spacing
const gdcm::Tag tagNumberOfFrames(0x0028, 0x0008); // number of frames
try
{
Image::Pointer image = preLoadedImageBlock.IsNull() ? Image::New() : preLoadedImageBlock;
CallbackCommand *command = callback ? new CallbackCommand(callback) : 0;
bool initialize_node = false;
/* special case for Philips 3D+t ultrasound images */
if ( DicomSeriesReader::IsPhilips3DDicom(filenames.front().c_str()) )
{
// TODO what about imageBlockDescriptor?
// TODO what about preLoadedImageBlock?
ReadPhilips3DDicom(filenames.front().c_str(), image);
initialize_node = true;
}
else
{
/* default case: assume "normal" image blocks, possibly 3D+t */
bool canLoadAs4D(true);
gdcm::Scanner scanner;
ScanForSliceInformation(filenames, scanner);
// need non-const access for map
gdcm::Scanner::MappingType& tagValueMappings = const_cast(scanner.GetMappings());
std::list imageBlocks = SortIntoBlocksFor3DplusT( filenames, tagValueMappings, sort, canLoadAs4D );
unsigned int volume_count = imageBlocks.size();
imageBlockDescriptor.SetSeriesInstanceUID( DicomSeriesReader::ConstCharStarToString( scanner.GetValue( filenames.front().c_str(), tagSeriesInstanceUID ) ) );
imageBlockDescriptor.SetSOPClassUID( DicomSeriesReader::ConstCharStarToString( scanner.GetValue( filenames.front().c_str(), tagSOPClassUID ) ) );
imageBlockDescriptor.SetModality( DicomSeriesReader::ConstCharStarToString( scanner.GetValue( filenames.front().c_str(), tagModality ) ) );
imageBlockDescriptor.SetNumberOfFrames( ConstCharStarToString( scanner.GetValue( filenames.front().c_str(), tagNumberOfFrames ) ) );
imageBlockDescriptor.SetPixelSpacingInformation( ConstCharStarToString( scanner.GetValue( filenames.front().c_str(), tagPixelSpacing ) ),
ConstCharStarToString( scanner.GetValue( filenames.front().c_str(), tagImagerPixelSpacing ) ) );
GantryTiltInformation tiltInfo;
// check possibility of a single slice with many timesteps. In this case, don't check for tilt, no second slice possible
if ( !imageBlocks.empty() && imageBlocks.front().size() > 1 && correctTilt)
{
// check tiltedness here, potentially fixup ITK's loading result by shifting slice contents
// check first and last position slice from tags, make some calculations to detect tilt
std::string firstFilename(imageBlocks.front().front());
// calculate from first and last slice to minimize rounding errors
std::string secondFilename(imageBlocks.front().back());
std::string imagePosition1( ConstCharStarToString( tagValueMappings[ firstFilename.c_str() ][ tagImagePositionPatient ] ) );
std::string imageOrientation( ConstCharStarToString( tagValueMappings[ firstFilename.c_str() ][ tagImageOrientation ] ) );
std::string imagePosition2( ConstCharStarToString( tagValueMappings[secondFilename.c_str() ][ tagImagePositionPatient ] ) );
bool ignoredConversionError(-42); // hard to get here, no graceful way to react
Point3D origin1( DICOMStringToPoint3D( imagePosition1, ignoredConversionError ) );
Point3D origin2( DICOMStringToPoint3D( imagePosition2, ignoredConversionError ) );
Vector3D right; right.Fill(0.0);
Vector3D up; right.Fill(0.0); // might be down as well, but it is just a name at this point
DICOMStringToOrientationVectors( imageOrientation, right, up, ignoredConversionError );
tiltInfo = GantryTiltInformation ( origin1, origin2, right, up, filenames.size()-1 );
correctTilt = tiltInfo.IsSheared() && tiltInfo.IsRegularGantryTilt();
}
else
{
correctTilt = false; // we CANNOT do that
}
imageBlockDescriptor.SetHasGantryTiltCorrected( correctTilt );
if (volume_count == 1 || !canLoadAs4D || !load4D)
{
-
DcmIoType::Pointer io;
image = MultiplexLoadDICOMByITK( imageBlocks.front(), correctTilt, tiltInfo, io, command, preLoadedImageBlock ); // load first 3D block
imageBlockDescriptor.AddFiles(imageBlocks.front()); // only the first part is loaded
imageBlockDescriptor.SetHasMultipleTimePoints( false );
FixSpacingInformation( image, imageBlockDescriptor );
CopyMetaDataToImageProperties( imageBlocks.front(), scanner.GetMappings(), io, imageBlockDescriptor, image);
initialize_node = true;
}
else if (volume_count > 1)
{
imageBlockDescriptor.AddFiles(filenames); // all is loaded
imageBlockDescriptor.SetHasMultipleTimePoints( true );
DcmIoType::Pointer io;
image = MultiplexLoadDICOMByITK4D( imageBlocks, imageBlockDescriptor, correctTilt, tiltInfo, io, command, preLoadedImageBlock );
initialize_node = true;
}
-
}
if (initialize_node)
{
// forward some image properties to node
node.GetPropertyList()->ConcatenatePropertyList( image->GetPropertyList(), true );
+ std::string patientName = node.GetProperty("dicom.patient.PatientsName")->GetValueAsString();
+
node.SetData( image );
+ node.SetName(patientName);
setlocale(LC_NUMERIC, previousCLocale);
std::cin.imbue(previousCppLocale);
}
MITK_DEBUG << "--------------------------------------------------------------------------------";
MITK_DEBUG << "DICOM files loaded (from series UID " << imageBlockDescriptor.GetSeriesInstanceUID() << "):";
MITK_DEBUG << " " << imageBlockDescriptor.GetFilenames().size() << " '" << imageBlockDescriptor.GetModality() << "' files (" << imageBlockDescriptor.GetSOPClassUIDAsString() << ") loaded into 1 mitk::Image";
MITK_DEBUG << " multi-frame: " << (imageBlockDescriptor.IsMultiFrameImage()?"Yes":"No");
MITK_DEBUG << " reader support: " << ReaderImplementationLevelToString(imageBlockDescriptor.GetReaderImplementationLevel());
MITK_DEBUG << " pixel spacing type: " << PixelSpacingInterpretationToString( imageBlockDescriptor.GetPixelSpacingType() ) << " " << image->GetGeometry()->GetSpacing()[0] << "/" << image->GetGeometry()->GetSpacing()[0];
MITK_DEBUG << " gantry tilt corrected: " << (imageBlockDescriptor.HasGantryTiltCorrected()?"Yes":"No");
MITK_DEBUG << " 3D+t: " << (imageBlockDescriptor.HasMultipleTimePoints()?"Yes":"No");
MITK_DEBUG << "--------------------------------------------------------------------------------";
}
catch (std::exception& e)
{
// reset locale then throw up
setlocale(LC_NUMERIC, previousCLocale);
std::cin.imbue(previousCppLocale);
MITK_DEBUG << "Caught exception in DicomSeriesReader::LoadDicom";
throw e;
}
}
void
DicomSeriesReader::ScanForSliceInformation(const StringContainer &filenames, gdcm::Scanner& scanner)
{
const gdcm::Tag tagImagePositionPatient(0x0020,0x0032); //Image position (Patient)
scanner.AddTag(tagImagePositionPatient);
const gdcm::Tag tagSeriesInstanceUID(0x0020, 0x000e); // Series Instance UID
scanner.AddTag(tagSeriesInstanceUID);
const gdcm::Tag tagImageOrientation(0x0020,0x0037); //Image orientation
scanner.AddTag(tagImageOrientation);
const gdcm::Tag tagSliceLocation(0x0020, 0x1041); // slice location
scanner.AddTag( tagSliceLocation );
const gdcm::Tag tagInstanceNumber(0x0020, 0x0013); // (image) instance number
scanner.AddTag( tagInstanceNumber );
const gdcm::Tag tagSOPInstanceNumber(0x0008, 0x0018); // SOP instance number
scanner.AddTag( tagSOPInstanceNumber );
const gdcm::Tag tagPixelSpacing(0x0028, 0x0030); // Pixel Spacing
scanner.AddTag( tagPixelSpacing );
const gdcm::Tag tagImagerPixelSpacing(0x0018, 0x1164); // Imager Pixel Spacing
scanner.AddTag( tagImagerPixelSpacing );
const gdcm::Tag tagModality(0x0008, 0x0060); // Modality
scanner.AddTag( tagModality );
const gdcm::Tag tagSOPClassUID(0x0008, 0x0016); // SOP Class UID
scanner.AddTag( tagSOPClassUID );
const gdcm::Tag tagNumberOfFrames(0x0028, 0x0008); // number of frames
scanner.AddTag( tagNumberOfFrames );
scanner.Scan(filenames); // make available image information for each file
}
std::list
DicomSeriesReader::SortIntoBlocksFor3DplusT(
const StringContainer& presortedFilenames,
const gdcm::Scanner::MappingType& tagValueMappings,
bool /*sort*/,
bool& canLoadAs4D )
{
std::list imageBlocks;
// ignore sort request, because most likely re-sorting is now needed due to changes in GetSeries(bug #8022)
StringContainer sorted_filenames = DicomSeriesReader::SortSeriesSlices(presortedFilenames);
std::string firstPosition;
unsigned int numberOfBlocks(0); // number of 3D image blocks
static const gdcm::Tag tagImagePositionPatient(0x0020,0x0032); //Image position (Patient)
// loop files to determine number of image blocks
for (StringContainer::const_iterator fileIter = sorted_filenames.begin();
fileIter != sorted_filenames.end();
++fileIter)
{
gdcm::Scanner::TagToValue tagToValueMap = tagValueMappings.find( fileIter->c_str() )->second;
if(tagToValueMap.find(tagImagePositionPatient) == tagToValueMap.end())
{
// we expect to get images w/ missing position information ONLY as separated blocks.
assert( presortedFilenames.size() == 1 );
numberOfBlocks = 1;
break;
}
std::string position = tagToValueMap.find(tagImagePositionPatient)->second;
MITK_DEBUG << " " << *fileIter << " at " << position;
if (firstPosition.empty())
{
firstPosition = position;
}
if ( position == firstPosition )
{
++numberOfBlocks;
}
else
{
break; // enough information to know the number of image blocks
}
}
MITK_DEBUG << " ==> Assuming " << numberOfBlocks << " time steps";
if (numberOfBlocks == 0) return imageBlocks; // only possible if called with no files
// loop files to sort them into image blocks
unsigned int numberOfExpectedSlices(0);
for (unsigned int block = 0; block < numberOfBlocks; ++block)
{
StringContainer filesOfCurrentBlock;
for ( StringContainer::const_iterator fileIter = sorted_filenames.begin() + block;
fileIter != sorted_filenames.end();
//fileIter += numberOfBlocks) // TODO shouldn't this work? give invalid iterators on first attempts
)
{
filesOfCurrentBlock.push_back( *fileIter );
for (unsigned int b = 0; b < numberOfBlocks; ++b)
{
if (fileIter != sorted_filenames.end())
++fileIter;
}
}
imageBlocks.push_back(filesOfCurrentBlock);
if (block == 0)
{
numberOfExpectedSlices = filesOfCurrentBlock.size();
}
else
{
if (filesOfCurrentBlock.size() != numberOfExpectedSlices)
{
MITK_WARN << "DicomSeriesReader expected " << numberOfBlocks
<< " image blocks of "
<< numberOfExpectedSlices
<< " images each. Block "
<< block
<< " got "
<< filesOfCurrentBlock.size()
<< " instead. Cannot load this as 3D+t"; // TODO implement recovery (load as many slices 3D+t as much as possible)
canLoadAs4D = false;
}
}
}
return imageBlocks;
}
Image::Pointer
DicomSeriesReader
::MultiplexLoadDICOMByITK(const StringContainer& filenames, bool correctTilt, const GantryTiltInformation& tiltInfo, DcmIoType::Pointer& io, CallbackCommand* command, Image::Pointer preLoadedImageBlock)
{
io = DcmIoType::New();
io->SetFileName(filenames.front().c_str());
io->ReadImageInformation();
if (io->GetPixelType() == itk::ImageIOBase::SCALAR)
{
return MultiplexLoadDICOMByITKScalar(filenames, correctTilt, tiltInfo, io, command ,preLoadedImageBlock);
}
else if (io->GetPixelType() == itk::ImageIOBase::RGB)
{
return MultiplexLoadDICOMByITKRGBPixel(filenames, correctTilt, tiltInfo, io, command ,preLoadedImageBlock);
}
else
{
return NULL;
}
}
Image::Pointer
DicomSeriesReader
::MultiplexLoadDICOMByITK4D( std::list& imageBlocks, ImageBlockDescriptor imageBlockDescriptor, bool correctTilt, const GantryTiltInformation& tiltInfo, DcmIoType::Pointer& io, CallbackCommand* command, Image::Pointer preLoadedImageBlock)
{
io = DcmIoType::New();
io->SetFileName(imageBlocks.front().front().c_str());
io->ReadImageInformation();
if (io->GetPixelType() == itk::ImageIOBase::SCALAR)
{
return MultiplexLoadDICOMByITK4DScalar(imageBlocks, imageBlockDescriptor, correctTilt, tiltInfo, io, command ,preLoadedImageBlock);
}
else if (io->GetPixelType() == itk::ImageIOBase::RGB)
{
return MultiplexLoadDICOMByITK4DRGBPixel(imageBlocks, imageBlockDescriptor, correctTilt, tiltInfo, io, command ,preLoadedImageBlock);
}
else
{
return NULL;
}
}
-
-} // end namespace mitk
+} // end namespace mitk
\ No newline at end of file
diff --git a/Core/Code/IO/mitkFileReaderRegistry.cpp b/Core/Code/IO/mitkFileReaderRegistry.cpp
index 682e6237f2..11805052d7 100644
--- a/Core/Code/IO/mitkFileReaderRegistry.cpp
+++ b/Core/Code/IO/mitkFileReaderRegistry.cpp
@@ -1,114 +1,114 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
Copyright (c) German Cancer Research Center,
Division of Medical and Biological Informatics.
All rights reserved.
This software is distributed WITHOUT ANY WARRANTY; without
even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE.
See LICENSE.txt or http://www.mitk.org for details.
===================================================================*/
#include "mitkFileReaderRegistry.h"
#include "mitkIMimeTypeProvider.h"
#include "mitkCoreServices.h"
// Microservices
#include
#include
#include
#include
#include "itksys/SystemTools.hxx"
mitk::FileReaderRegistry::FileReaderRegistry()
{
}
mitk::FileReaderRegistry::~FileReaderRegistry()
{
for (std::map >::iterator iter = m_ServiceObjects.begin(),
end = m_ServiceObjects.end(); iter != end; ++iter)
{
iter->second.UngetService(iter->first);
}
}
-mitk::MimeType mitk::FileReaderRegistry::GetMimeTypeForExtension(const std::string& extension, us::ModuleContext* context)
+mitk::MimeType mitk::FileReaderRegistry::GetMimeTypeForFile(const std::string& path, us::ModuleContext* context)
{
mitk::CoreServicePointer mimeTypeProvider(mitk::CoreServices::GetMimeTypeProvider(context));
- std::vector mimeTypes = mimeTypeProvider->GetMimeTypesForExtension(extension);
+ std::vector mimeTypes = mimeTypeProvider->GetMimeTypesForFile(path);
if (mimeTypes.empty())
{
return MimeType();
}
else
{
return mimeTypes.front();
}
}
std::vector mitk::FileReaderRegistry::GetReferences(const MimeType& mimeType, us::ModuleContext* context)
{
std::string filter = us::LDAPProp(us::ServiceConstants::OBJECTCLASS()) == us_service_interface_iid() &&
us::LDAPProp(IFileReader::PROP_MIMETYPE()) == mimeType.GetName();
return context->GetServiceReferences(filter);
}
mitk::IFileReader* mitk::FileReaderRegistry::GetReader(const mitk::FileReaderRegistry::ReaderReference& ref, us::ModuleContext* context)
{
us::ServiceObjects serviceObjects = context->GetServiceObjects(ref);
mitk::IFileReader* reader = serviceObjects.GetService();
m_ServiceObjects.insert(std::make_pair(reader, serviceObjects));
return reader;
}
std::vector mitk::FileReaderRegistry::GetReaders(const MimeType& mimeType, us::ModuleContext* context )
{
std::vector result;
if (!mimeType.IsValid()) return result;
std::vector > refs = GetReferences(mimeType, context);
std::sort(refs.begin(), refs.end());
result.reserve(refs.size());
// Translate List of ServiceRefs to List of Pointers
for (std::vector >::const_reverse_iterator iter = refs.rbegin(), end = refs.rend();
iter != end; ++iter)
{
us::ServiceObjects serviceObjects = context->GetServiceObjects(*iter);
mitk::IFileReader* reader = serviceObjects.GetService();
m_ServiceObjects.insert(std::make_pair(reader, serviceObjects));
result.push_back(reader);
}
return result;
}
void mitk::FileReaderRegistry::UngetReader(mitk::IFileReader* reader)
{
std::map >::iterator readerIter =
m_ServiceObjects.find(reader);
if (readerIter != m_ServiceObjects.end())
{
readerIter->second.UngetService(reader);
m_ServiceObjects.erase(readerIter);
}
}
void mitk::FileReaderRegistry::UngetReaders(const std::vector& readers)
{
for (std::vector::const_iterator iter = readers.begin(), end = readers.end();
iter != end; ++iter)
{
this->UngetReader(*iter);
}
}
diff --git a/Core/Code/IO/mitkFileReaderRegistry.h b/Core/Code/IO/mitkFileReaderRegistry.h
index b0abe285cb..6cb13d2f85 100644
--- a/Core/Code/IO/mitkFileReaderRegistry.h
+++ b/Core/Code/IO/mitkFileReaderRegistry.h
@@ -1,85 +1,85 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
Copyright (c) German Cancer Research Center,
Division of Medical and Biological Informatics.
All rights reserved.
This software is distributed WITHOUT ANY WARRANTY; without
even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE.
See LICENSE.txt or http://www.mitk.org for details.
===================================================================*/
#ifndef FileReaderRegistry_H_HEADER_INCLUDED_C1E7E521
#define FileReaderRegistry_H_HEADER_INCLUDED_C1E7E521
#include
#include
#include
// Microservices
#include
#include
#include
namespace mitk {
class MimeType;
/**
* @ingroup IO
*
* Provides convenient access to mitk::IFileReader instances and reading
* files into mitk::BaseData types.
*
* \note The life-time of all mitk::IFileReader objects returned by an
* instance of this class ends with the destruction of that instance.
*/
class MITK_CORE_EXPORT FileReaderRegistry
{
public:
typedef us::ServiceReference ReaderReference;
FileReaderRegistry();
~FileReaderRegistry();
/**
- * @brief Get the highest ranked mime-type for the given extension.
+ * @brief Get the highest ranked mime-type for the given file name.
* @param extension A file name extension without a leading dot.
* @param context
* @return The highest ranked mime-type containing \c extension in
* its extension list.
*/
- static MimeType GetMimeTypeForExtension(const std::string& extension, us::ModuleContext* context = us::GetModuleContext());
+ static MimeType GetMimeTypeForFile(const std::string& path, us::ModuleContext* context = us::GetModuleContext());
static std::vector GetReferences(const MimeType& mimeType, us::ModuleContext* context = us::GetModuleContext());
mitk::IFileReader* GetReader(const ReaderReference& ref, us::ModuleContext* context = us::GetModuleContext());
std::vector GetReaders(const MimeType& mimeType, us::ModuleContext* context = us::GetModuleContext());
void UngetReader(mitk::IFileReader* reader);
void UngetReaders(const std::vector& readers);
private:
// purposely not implemented
FileReaderRegistry(const FileReaderRegistry&);
FileReaderRegistry& operator=(const FileReaderRegistry&);
std::map > m_ServiceObjects;
};
} // namespace mitk
#endif /* FileReaderRegistry_H_HEADER_INCLUDED_C1E7E521 */
diff --git a/Core/Code/IO/mitkFileWriterSelector.cpp b/Core/Code/IO/mitkFileWriterSelector.cpp
index 86ff419f0b..77e59bf989 100644
--- a/Core/Code/IO/mitkFileWriterSelector.cpp
+++ b/Core/Code/IO/mitkFileWriterSelector.cpp
@@ -1,360 +1,356 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
Copyright (c) German Cancer Research Center,
Division of Medical and Biological Informatics.
All rights reserved.
This software is distributed WITHOUT ANY WARRANTY; without
even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE.
See LICENSE.txt or http://www.mitk.org for details.
===================================================================*/
#include "mitkFileWriterSelector.h"
#include
#include
#include
#include
#include
#include